0
0
0
0
专栏/.../

TiDB 悲观事务模式和Mysql的表象区别

 zzw6776  发表于  2021-12-16
原创

【是否原创】是
【首发渠道】个人博客
【首发渠道链接】https://www.cnblogs.com/MRLL/p/15696552.html
【正文】
强烈建议先阅读完这篇文章,本篇文章只提到了我目前遇到的情况以及衍生出来考虑的问题,是肯定不全的~ 欢迎指正
https://zhuanlan.zhihu.com/p/87608202

前篇

tidb在3.0.8之后默认开启悲观事务,但是autocommit 事务优先采用乐观事务提交,翻译一下这句话就是,如果是不手动开启事务的场景,同时两个insert/update语句还是走的乐观锁机制,就有概率触发 write conflict 触发方式如图:

SET @@tidb_txn_mode = ''; 调整本次会话为乐观模式

image

解决 write conflict

有两个办法

1:在默认悲观事务的情况下开启事务(有点绕,说的再简单点就是java要加上 @Transactional 注解)

2:开启乐观事务重试机制,并重新建立tidb连接(新建立的连接才会用上新参数)

SET GLOBAL tidb_disable_txn_auto_retry = OFF;
SET GLOBAL tidb_retry_limit = 10;

第一点很好理解,问题出在于第二点,因为官方原话为

TiDB 默认不进行事务重试,因为重试事务可能会导致更新丢失,从而破坏可重复读的隔离级别。

当事务中存在依赖查询结果来更新的语句时,重试将无法保证事务原本可重复读的隔离级别,最终可能导致结果与预期出现不一致。

这两句话其实很难理解,让我们来看下图的例子

例子1

同样要先 SET @@tidb_txn_mode = ''; 调整本次会话为乐观模式,然后开启重试机制

image

最后结果也就是t6的更新其实并没有成功,因为实际这个时候的id=1数据已经被session B更新为了status=0,在重试的时候自然匹配不上更新条件.然后我们再回过头来看官方的原话,因为重试事务可能会导致更新丢失.但是这个真的是更新丢失吗,我们回想下在如果以上操作在mysql下的场景,在t6这一步的时候,mysql会触发当前读,然后直接告诉你0 row affectied(忘记截图了,可以自己试下),那么在t9这个时间的时候,mysql和tidb的表象其实是一致的,区别在于中间更新的时候返回的影响行数

例子2

让我们再来看一个例子

session a session b
t1 begin
t2 begin
t3 update tidb set status =0 where id = 1
t4 update tidb set status =1 where id = 1
t5 commit
t6 commit
t7 SELECT * from tidb where id = 1 id name status 1 tidb 0

可以看出在这个例子里,update数据的时间不重要,commit的时间才重要,后面commit的数据会把先commit的数据进行覆盖,对于mysql来说,在t4这一步就会被阻断,直到session a提交事务,所以在这个场景下,tidb和mysql是完全不一样的

总结下

1.可能会造成返回的更新条数与实际情况不同,但是最终表象会和mysql一致

2.自然时间的更新顺序将没有参考意义,数据的最新记录与commit时间有关,这一点和mysql不一致

幻读

再额外说下幻读

可以先看下这个文章看下mysql的幻读
https://www.wolai.com/jtaGKJqoUusS5mmA5NqoG1

由于tidb没有间隙锁

所以再这个场景下,tidb的表象也和mysql不一致

session a session b
t1 begin;
t2 begin;
t3 SELECT * from tidb where id >3 for UPDATE
t4 INSERT INTO tidb (id, name, status) VALUES (12, 'tidb', 7);
t5 commit;
t6 SELECT * from tidb where id >3 for UPDATE
可以查询到insert的数据

在mysql的场景下,在t4这一步就会被阻塞,直到t3加的锁被释放

其他参考文章

TiDB和MySQL的锁一些分析比对 技术文章

【是否原创】是 【首发渠道】TiDB 社区 【首发渠道链接】其他平台首发请附上对应链接 【正文】 [image] 图1 锁分类图 一、悲观锁和乐观锁 TiDB一开始是乐观锁,但自TiDB3.0版本开始,支持悲观事务,并且在3.0.8版本开始默认使用悲观事务,支持悲观锁,查看事务:show variables like ‘%tidb_txn_mode%’; [image] 悲观锁的…


TiDB 4.0 新特性前瞻:白话“悲观锁” 原理解读

作者:Shirly 如果说在 TiDB 3.0 中,悲观锁是 “千呼万唤始出来,犹抱琵琶半遮面”。那么在 TiDB 4.0 中,悲观锁在经历了市场与时光的考验后,无论是性能还是稳定性都能够 “轻拢慢撚抹复挑,初为《霓裳》后《六幺》”,欢迎大家尝鲜与反馈。本文将从使用者的角度,介绍悲观锁的使用与注意事项,主要分为以下几方面: 白话悲观锁 TiDB 悲观锁的使用和常见现象 TiDB 悲观锁与…

0
0
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论