一、一致性非锁定读
一致性非锁定读(consistent nonlocking read)是指InnoDB引擎通过行多版本控制(multi versioning)的方式来当前执行时间数据库中的行。如果读取的行正在执行update/delete操作,此时读操作不会等待锁的释放,而是读取了行的快照。
该方案是通过Undo段来实现的。Undo 段主要用于事务中回滚数据。快照数据就是当前行数据的历史版本,每个记录可以有多个版本。由此带来的并发控制,称为多版本并发控制(Multi Version Concrrency Controll,MVCC).
在事务隔离级别为READ COMMITED和REPEATABLE READ的事务隔离级别下,InnoDB引擎使用的是一致性非 锁定读。在READ COMMIT隔离级别下,对于快照数据,非一致性读总是读取被锁定行的最新一份数据快照;而REPEATABLE READ级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。
例如以下例子:
在会话A中执行以下SQL:
BEGIN;
SELECT * FROM t4 WHERE a=1;
然后打开会话B,执行以下SQL:
BEGIN ;
UPDATE t4 SET a=3 WHERE a=1;
此时,在会话B中加了一个X锁,如果在会话A中再次执行SELECT * FROM t4 WHERE a=1;由于非锁定一致性读,在READ COMMIT和REPEATABLE READ下,都得到以下结果:
此时,回到会话B,提交事务:
COMMIT;
SELECT @@tx_isolation;
SELECT * FROM t4 WHERE a=1;后的结果为空。
此时在会话A中执行SELECT * FROM t4 WHERE a=1发现:
读取的还是事务开始时的版本。把A会话的事务提交后,再查询,结果就和B一样的了。
这是REPEATABLE READ事务隔离级别的情况,如果是READ COMMITED级别中,在会话没提示事务之前,查询到的结果是和B一样的,是数据已经查询不到了,这违反了事务ACID的I特征,即隔离性。
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@tx_isolation;
二、一致性锁定读
InnoDB引擎对于SELECT语句一般支持两种一致性的锁定读操作:
• SELECT … FOR UPDATE;
• SELECT … LOCK IN SHARE MODE;
第一种加X锁,第2种加S锁,对于一致性非锁定读,即使行被执行了FOR UPDATE,也是可以进行行读取的。这两种方式必须在同一个事务中,即在BEGIN,START TRANSACTION或AUTOCOMMIT=0.
参考《MySQL技术内幕 -InnoDB存储引擎》整理,如侵权请联系vinin@163.com。