简介
在很长一段时间里我都认为在Mysql中事务的开始时间点就是我们执行的begin/start transaction执行后,直到有一天在聊天群里发现一个人提出的疑惑。大致意思如下:
sessionA | sessionB | |
---|---|---|
t1 | start transaction; | |
t2 | start transaction; | |
t3 | INSERT INTO t_score (id, user_name, score, kemu) VALUES (‘1’, ‘mac’, ‘100’, ‘语文’); | |
t4 | commit; | |
t5 | select * from t_score; |
注意Mysql的隔离级别为可重复读
现在的问题是sessionA能读到sessionB插入的数据吗?因为Mysql的隔离级别是可重复读,所以我想都没想这必定是查不到的。如果能查到,那岂不是和可重复读自相矛盾了。
但是我在Mysql上试验完之后发现,sessionB插入的数据sessionA是能查到的,对于这个结果我简直不敢相信。
再次试验
对于上面的结果我无法理解,于是又尝试下面的执行顺序:
sessionA | sessionB | |
---|---|---|
t1 | start transaction; | |
t2 | start transaction; | |
t3 | select * from t_score; | |
t4 | INSERT INTO t_score (id, user_name, score, kemu) VALUES (‘1’, ‘mac’, ‘100’, ‘语文’); | |
t5 | commit; | |
t6 | select * from t_score; |
对于sessionA的第一次查询结果没什么好奇怪的肯定查不到,因为此时sessionB都还没有开始插入数据。sessionA的第二次查询按照可重复读的逻辑来说,应该也是查不到的。事实证明的确跟我们想的一样是无法查到的。
原因
一般情况下我们都认为begin/start transaction是事务开始的时间点,也就是一旦我们执行了start transaction事务就开始了,其实这是错误的。事务开始的真正时间点是start transaction之后执行的第一条语句,不管是什么语句,不管成功与否。
如果我们想要实现在执行start transaction后立马开启事务,需要加上with consistent snapshot
才行。关于这点可以参考Mysql官方文档中的描述:
https://dev.mysql.com/doc/refman/5.7/en/commit.html
而这条语句的真正含义是:执行start transaction同时建立本事务一致性读的快照,而不是等到执行第一条语句是才开始事务并建立一致性读的快照。
对于文中最初的例子,我们修改start transaction
为start transaction with consistent snapshot
,然后按照之前的顺序再次执行,最后sessionA是无法读取到sessionB插入的数据的。
原文始发于微信公众号(一只菜鸟程序员):Mysql事务的开始时间点
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72868.html