A type of read operation used for UPDATE statements, that is a combination of read committed and consistent read. When an UPDATE statement examines a row that is already locked, InnoDB returns the latest committed version to MySQL so that MySQL can determine whether the row matches the WHERE condition of the UPDATE. If the row matches (must be updated), MySQL reads the row again, and this time InnoDB either locks it or waits for a lock on it. This type of read operation can only happen when the transaction has the read committed isolation level, or when the innodb_locks_unsafe_for_binlog option is enabled.
简单来说,semi-consistent read是read committed与consistent read两者的结合。一个update语句,如果读到一行已经加锁的记录,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。若满足,则MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)。
semi-consistent read只会发生在read committed隔离级别下,或者是参数innodb_locks_unsafe_for_binlog=ON。
create table semi(a int not null); insert into semi values (1),(2),(3),(4),(5),(6),(7);
1. read commit 级别演示: 读取不到满足条件的数据
session 2不需要等待session 1,虽然session 1的更新后项满足session 2的条件,但是由于session 2进行了semi-consistent read,读取到的记录的为(1-7),不满足session 2的更新where条件,因此session 2直接返回。
2. repeatable read 演示 :等待满足条件的数据
3. repeatable read 演示: 不满足条件,直接释放数据
session 1在session 2开始前已经提交,session 2可以进行semi-consistent read。并且读到的都是session 1的更新后项,完成加锁。但是由于更新后项均不满足session 2的where条件,session 2会释放所有行上的锁(由MySQL Server层判断并释放行锁)。
此时,session 1再次执行select * from t1 lock in share mode语句,直接成功。因为session 2已经将所有的行锁提前释放。
优点
- 减少了更新同一行记录时的冲突,减少锁等待
-
可以提前放锁,进一步减少并发冲突概率
缺点
-
非冲突串行化策略,因此对于binlog来说,是不安全的
两条语句,根据执行顺序与提交顺序的不同,通过binlog复制到备库后的结果也会不同。不是完全的冲突串行化结果。
因此只能在事务的隔离级别为read committed(或以下),或者设置了innodb_locks_unsafe_for_binlog=ON的情况下才能够使用。
出处:
何登成:MySQL+InnoDB semi-consitent read原理及实现分析