幻读
幻读是指在同一个事务中,在不同的时间点执行相同的查询,返回结果数据集合不相同,例如,一个SELECT语句被执行两次,一个行记录在第二次返回的结果中与第一次返回的结果中不相同,该行记录被称为幻读。
假设,数据表child存在索引id,期望读取并锁住id值大于100的全部行记录,然后执行更新操作,如下所示:
如上所示,该查询从id索引值大于100的记录开始扫描索引,假设,数据表child也包括索引值等于90、102的行记录,如果没有在索引值等于90、102之间的地址间隙中设置锁,则其他会话可能在此地址间隙中插入索引值等于101的记录,如果再次执行相同的查询操作,则第二次返回的结果数据集合中包括索引值等于101的新行记录,则该行记录是一个幻读,很明显地,该查询操作违反了事务隔离级别的原则,在同一个事务中多次执行相同的查询操作返回的结果数据集合应该都相同。
为了阻止幻读的发生,InnoDB使用一种被称之为下一键锁的算法,下一键锁是索引记录锁与间隙锁的综合。InnoDB在查询或者检索的过程中以一键锁的算法执行行级锁,对遇到的每个行记录设置共享锁或者排他锁,实际上,行级锁是索引记录锁,另外,在索引记录上的下一键锁会影响索引记录之前的地址间隙,也就是,下一键锁包括一个索引记录锁与索引记录之前的间隙锁。如果一个会话对索引记录R设置了一个共享锁或者排他锁,则其他会话在索引顺序上不能立刻在R之前的间隙中插入一个新的记录。
当InnoDB扫描索引,也可以锁住在最后的索引记录之后的间隙,如前面的例子中,索引值等于102之后的间隙也设置了间隙锁。
下一键锁可以用于唯一性检查的场景中,例如,以共享的模式查询行记录,对比待插入记录,没有发现重复键,则可以安全地插入新记录。
事务调度
InnoDB使用竞争感知的事务调度(英文全称是Contention-Aware Transaction Scheduling ,首字母缩写是CATS)算法优先处理处于等待锁状态的事务。当多个事务等待获取对相同对象的锁时,InnoDB使用CATS算法确定优先获取到锁的事务。
CATS算法使用一个调度权重优先处理等待的事务,是基于一个事务阻塞其他事务的总数确定该权重。例如,如果存在两个事务等待对同一个对象的锁,则阻塞最多事务的事务的调度权重最大,如果事务的权重相同,则优先处理等待时间最长的事务。
系统数据表INFORMATION_SCHEMA.INNODB_TRX包括事务与锁的统计信息,其中可以查询列TRX_SCHEDULE_WEIGHT,该列是事务调度权重。