一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过 行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放,相反地,InnoDB存储引擎会去读取行的一个快照数据。
如图,直观地展现了InnoDB存储引擎一致性的非锁定读。之所以称其为非锁定读,因为不需要等待访问的行上X锁的释放。快照数据是指该行的之前版本的数据,该是先是通过undo段来完成。而undo用来在事务中回滚数据,因此快照数据本身是没有额外的开销。此外,读取快照数据是不需要上锁的,因为没有事务需要对历史的数据进行修改操作。
非锁定读机制极大地提高了数据库的并发性,这是InnoDB存储引擎的默认读取方式。但是在不同事务隔离级别下,读取的方式不一定相同。此外,即使都是使用非锁定的一致性读,但是对于快照数据的定义也各不相同。在事务隔离级别READ COMMITTED 和REPEATABLE READ下,InnoDB都使用非锁定一致性读。然而,对于快照数据的定义却不同。在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总数读取被锁定行的最新的快照数据。而在REPEATABLE READ事务隔离级别下,对于快照数据,非锁定一致性读总是获取事务开始时的行数据版本。
快照数据其实就是当前行数据之前的历史版本,每行记录可能有多个版本,因此一行记录可能有不止一个快照数据,一般称这种技术为 行多版本技术。由此带来的并发控制,称之为多版本并发控制(Multi Version Concurrency Control, MVCC)。
一致性锁定读
在某些情况下,用户需要显示地对数据库读取操作进行加锁,以保证数据逻辑的一致性。而这要求数据库支持加锁语句,即使是对于SELECT的只读操作。InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作:
- SELECT…FOR UPDATE
- SELECT…LOCK IN SHARE MODE
SELECT…FOR UPDATE对读取的行记录加一个X锁;SELECT…LOCK IN SHARE MODE对读取的行记录加一个S锁。