这篇文章真是太厉害了,彻底解释清楚MVCC的原理。
问题:事务B的select语句和事务A的select语句分别是多少?
image.png务 C 没有显式地使用 begin/commit,表示这个 update 语句本身就是一个事务,语句完成的时候会自动提交。事务B由于操作update语句,属于当前读,所以会读取到3(因为C已经提交了)。
对于事务A,begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作 InnoDB 表的语句,事务才真正启动。如果你想要马上启动一个事务,可以使用 start transaction with consistent snapshot 这个命令。第一种启动方式,一致性视图是在执行第一个快照读语句时创建的;第二种启动方式,一致性视图是在执行 start transaction with consistent snapshot 时创建的。所以在select之前已经读取到快照了,结果就是1。
“快照”在 MVCC 里是怎么工作的?
image.png三个虚线箭头,就是 undo log。
image.png
一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:
版本未提交,不可见;
版本已提交,但是是在视图创建后提交的,不可见;
版本已提交,而且是在视图创建前提交的,可见。
更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。除了 update 语句外,select 语句如果加锁,也是当前读。
image.png这种情况下,事务 C’没提交,也就是说 (1,2) 这个版本上的写锁还没释放。而事务 B 是当前读,必须要读最新版本,而且必须加锁,因此就被锁住了,必须等到事务 C’释放这个锁,才能继续它的当前读。
所以行锁和一致性视图,不冲突。
网友评论