关于两个事务更新同一条记录引发的现象是否合理?

【 TiDB 使用环境`】啥环境都行
【 TiDB 版本】5,6 都有同样的现象
【遇到的问题】
【复现路径】
【问题现象及影响】
表t1,有两个字段,id和name,有一条记录,id是1,name是a,现开启两个客户端,即两个session,同时执行begin,开启事务,接下来在两个客户端执行以下语句,update t1 set name=‘aa’ where id=1,此时有一个客户端执行成功,可以看到影响了一行,另外一个客户端在等待,待第一个成功的客户端执行commit提交事务,第二个客户端的语句执行成功,影响行数是0,此时在第二个客户端执行select * from t1 where id=1,会看到name是a,没被有修改为aa,此种现象合理吗?第二个客户端没有执行commit或rollback结束事务。mysql同样操作会在第二个客户端看到name改成了aa,求大神科普!!!

这很正常吧,默认隔离级别可以认为对应mysql的rr

合理,默认是snapshot isolation+悲观锁 ,begin开启事务,能看到的数据是当时的数据,update被阻塞后会获取最新的数据以确认是否有符合的记录,但select还是bgin时的时点

1 个赞

mysql 里面第二个客户端执行update语句前和执行后的snapshot发生了变化?怎么解释update语句带来的影响呢?
select * from t1 where id=1;//这里看到的name是a
update t1 set name=‘aa’ where id=1;// 影响行数是0
select * from t1 where id=1;//这里看到的name是aa

你到底是看到的哪个值, 你后面这个begin开启事务了吗?

两个客户端都开了,原始数据如下:
mysql> select * from t1;
±—±-----±-----+
| id | name |
±—±-----±-----+
| 1 | a |
±—±-----±-----+


client1:
begin; // 1
update t1 set name=‘aa’ where id=1; // 3
commit; // 6


client2:
begin; // 2
select name from t1 where id=1; // 4, name 是a
update t1 set name=‘aa’ where id=1; // 5
select name from t1 where id=1; // 7, name 是aa,这里为啥是mysql是aa,tidb是a
commit; // 8

mysql transaction-isolation设置是什么

REPEATABLE-READ

这得看隔离级别和锁采用那种模式

client2因为在第2步开启事务时值为a,所以在第7步时读取的是a,而不是aa。只要client2的事务没结束读取就一直是a。

5.7测试了,update确实这样,delete没问题,,估计第二个会话update执行后更新了readview

REPEATABLE-READ 隔离级别,可以根据需求,调整隔离级别。

TiDB里的START TRANSACTION,等价于MySQL里面的START TRANSACTION WITH CONSISTENT SNAPSHOT,你在MySQL里面使用这个语句启动事务,TiDB和MySQL的行为就一致了

在MySQL中,如果不带WITH CONSISTENT SNAPSHOT,MySQL里面RR隔离级别下,会在执行第一个SQL语句的时候创建SNAPSHOT,所以你第二个SESSION在执行UPDATE的时候才创建快照,这时name已经被第一个会话修改成aa了,所以你第二个会话在UPDATE在成功返回后,SELECT到的数据是aa

在TiDB中,事务启动瞬间就自动创建了SNAPSHOT,等价于MySQL中START TRANSACTION WITH CONSISTENT SNAPSHOT,这时在你的场景中,第二个会话在UPDATE在成功返回后,SELECT到的数据是a,也就是事务启动那一时刻的快照

mysql5.7,开启事务后,无论update语句是否影响了行记录,都会刷快照,mysql8.0则不会,和tidb一致。

请确认你5.7的隔离级别,start transaction with consistent snapshot只在RR下才有效果,RC下将被忽略掉

肯定是RR,要不还扯啥;
你有没实践过?实践一哈就知道了

首先,MySQL的5.7和8.0在ACID这一块儿,不会有这么大的差异,要不用户还怎么玩

其次,我在5.7下面的测试和你的结果不一样,时间戳在提示符上

麻烦多问一句哈,你测试的os版本是啥?

CentOS 7.7

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。