当今主流的MySQL存储引擎是InnoDB

InnoDB在对事务安全的支持上有几个主要特点:
在数据库系统中,一个事务是指:由一系列数据库操作组成的一个完整的逻辑过程。

提供了提交,回滚,崩溃恢复

InnoDB将每一句更新操作语句都当作事务处理,所以在进行大段的逻辑处理时,建议使用begin开启事务,然后进行多语句操作(这时有可能对多表进行修改),完成commit,那么如果中途出现问题,整个块会进行回滚,保证了数据的一致性。

ACID

数据库事务是否正确执行,根据ACID来判定,有些概念性的解释是从wiki上搬来的方便理解

A(Atomicity)原子性

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样

C(Consistency)一致性

在事务开始之前和事务结束以后,数据库的完整性没有被破坏

I(Isolation)隔离性

数据库允许多个并发事务同时对齐数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括

读未提交(Read uncommitted)
允许脏读取,但不允许更新数据。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

问题:A更新的数据,在没有提交的情况下,其他人就可以看到了,但不能动。
那么如果这个时候,B的更新条件是A正在更新的内容,那么就不可靠了,A并没有完成提交,如果回滚了,那么B的操作会产生数据不一致问题。B读到了脏数据,这时B就被迫“脏读”。

读提交(Read committed)
允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

问题:A在一个大事务中要多次获取数据a(a1),而在多次的间隙中,B修改并提交数据a(这时变成a2),那么A在下一次获取到的a(a2)是已被更新并提交的数据。那么A的大事务前后访问的数据产生了不一致,那么A的大事务计算的结果也是不可靠的。这时A就被迫“不可重复读”了。

不可重复读:读取到了不重复的已提交数据。
这里是被允许的

可重复读(Repeatable read)
禁止不可重复读取和脏读取,但是有时可能出现幻读数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

说明:这种方案是目前最能保证数据一致性安全的

幻读:指当事务不是独立执行时发生的一种现象。或者说事物与事物可以同时执行,导致其他事物的执行结果出现幻象。

共享读锁(S锁):读锁,若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。其他用户可以并发读取数据,但任何事务都不能获取数据上的排他锁,直到已释放所有共享锁。

排他写锁(X锁):写锁,若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。

可串行化的(Serializable)
提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

问题:虽然严格的保证了数据的完整性和一致性,但就目前的互联网高并发的业务场景是不适用的,执行效率远远不能满足需求。

D(Durability)持久性

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失

MVCC

Multi-Version Concurrency Control 多版本并发控制

锁机制

to be continued…