MySQL-MVCC、当前读、快照读
MVCC
多版本并发控制,通过保存数据在每个时间点的快照来实现。
InnoDB的MVCC通过在每行记录后面保存两个隐藏的列来实现,一列保存行的创建时间,一列保存行的删除时间,这个时间指的是系统版本号。

MVCC只在读已提交(RC)和可重复读(RR)两个隔离级别下工作。
快照读
读取记录的可见版本(有可能是历史版本),不用加锁。
简单的select操作,不包括 select ... lock in share mode
,select ... for update
。
RC:每次select都生成一个快照读,总是读取已提交的最新数据行
RR:第一次select生成快照读,读取上一次的快照
举例:
对于操作的前四行,即只有事务2已提交
读已提交: 未提交的事务id:[1,3] 最大的事务id:3 每一次查询都生成一个快照读,所以事务4的查询结果为29。
可重复读: RR第一次查询会生成快照,对一个事务,每次都沿用第一次的快照,直接复制一份之前的快照。 则在RR下,事务4再次查询的结果将会是29,而不是图中RC情况下的30。
当前读
读取的是最新版本,并且对读取的记录加锁。
select...lock in share mode (共享读锁)
select...for update
update , delete , insert
上面形式都属于当前读。
当前读的实现方式
使用next-key锁(行记录锁+Gap间隙锁)实现
RR级别怎样防止幻读?
RR级别下只要对 SELECT 操作也手动加行(X)锁即可类似 SERIALIZABLE 级别(它会对 SELECT 隐式加锁) 这里需要用 X锁, 用 LOCK IN SHARE MODE 拿到 S锁 后我们没办法做 写操作
SELECT `id` FROM `users` WHERE `id` = 1 FOR UPDATE; 如图,表t2有主键,score字段有索引idc_scaore,在事务中查询t2表score<80的记录,加了一个S锁(lock in share mode)。 在另一个事务中插入score=74,无法插入成功,因为有gap锁;插入score=90成功,因为不在此区间内。