Mysql Innodb 存储引擎 的 MVCC 如何保证可重复读

2017-10-19 17:59:41 +08:00
 sunkuku

例如按照下面时间顺序执行

因为 B 查询的数据要求是 createdAt < B.version && (deletedAt > B.version || deletedAt = null)

那么在事务 B 中,第一次查询到的记录和第二次查询到的记录是不一样的

这个怎么解释?

4978 次点击
所在节点    MySQL
9 条回复
ixiaohei
2017-10-19 18:32:30 +08:00
版本号和回滚段保证可重复读。
sunkuku
2017-10-19 18:37:43 +08:00
@ixiaohei
在我的例子里,A 的版本号小于 B。所以 B 是可以查到 A 添加的数据的,不是吗?
domty
2017-10-19 18:47:56 +08:00
Next-Key Lock
namedfish
2017-10-19 19:18:05 +08:00
在隔离级别为可重复读的情况下可以保证,详情可以 google mysql 隔离级别设置
ixiaohei
2017-10-19 20:13:26 +08:00
@sunkuku 我说错了,mysql 的 mvvc 的可以保证重复读,但是幻读是间隙锁还是什么东西保证的,具体可以读 mysql 官方文档。
另外你说的读到另外新插入的行这个是幻读,不是可重复读,可重复读这个隔离级别不保证幻读的。但是 mysql 可重复度貌似解决幻读(当时读文档很是因垂丝丁)
sunkuku
2017-10-23 15:21:35 +08:00
终于把这个问题研究清楚了。
首先感谢 @ixiaohei @domty @namedfish 的回答,但是你们的回答不能解释我提出的问题。
我想表达的是:在 Mysql 中,MVCC 如何保证不会读到并发事务的其他插入行?
这个问题在于很多文章在解释 MVCC 原理的时候有偏差。其实 Innodb 做的事情并不是简单的使用 createdAt 和 deletdAt,他用的是 tx_id 和 db_roll_ptr。其中 db_roll_ptr 指向 undo log。这个是 MVCC 的精髓所在。具体的我会写一篇文章,专门介绍下。
@ixiaohei 说的是接近的,靠的是事务号和回滚段。
sunkuku
2017-10-23 15:24:06 +08:00
这个是一个非常典型的误导讲解
http://blog.csdn.net/whoamiyang/article/details/51901888
后面我会说明他为什么是错的
ixiaohei
2017-10-23 17:51:45 +08:00
@sunkuku 你要研究深,还有个快照读和当前读区别,一般 mvcc 只是保证快照读可重复读,另外当前读应该就是间隙锁保证的(这个我不是很了解)
sunkuku
2017-10-31 11:08:17 +08:00
这个是 MVCC 实现原理的文章,放在团队博客上了
http://fridaytalk.org/archives/20/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/399013

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX