Write conflict写写冲突问题

【 TiDB 版本】
V7.1.2
【复现路径】
单表大量数据更新,两个简单update语句同时执行,报写冲突,设置得有set @@session.autocommit = 1;
【遇到的问题:问题现象及影响】
Write conflict, txnStartTS=445789926295863313, conflictStartTS=445789926020612100, conflictCommitTS=445789926308970497, key={tableID=1063399, tableName=ods_extend.qi_asr_result, handle=2933907}, originalKey=7480000000001039e75f7280000000002cc493, primary={tableID=1063399, tableName=ods_extend.qi_asr_result, indexID=2, indexValues={0, 2933907, }}, originalPrimaryKey=7480000000001039e75f6980000000000000020380000000000000000380000000002cc493, reason=Optimistic [try again later]

看这个异常,感觉是使用了乐观锁导致的问题,但我看了文档,TiDB中默认是使用的悲观锁,“使用悲观事务模式时,autocommit 事务首先尝试使用开销更小的乐观事务模式提交。如果发生了写冲突,重试时才会使用悲观事务提交。所以 tidb_retry_limit = 0 时,autocommit 事务遇到写冲突仍会报 Write Conflict 错误。” 我也看了我的tidb_retry_limit,这个值是10,我要如何才能解决这个问题?

我设置了这些参数:
SET @@SESSION.autocommit = 1;
SET @@SESSION.tidb_batch_insert = 1;
SET @@SESSION.tidb_batch_delete = 1;
SET @@SESSION.tidb_dml_batch_size = 1000;
SET @@SESSION.tidb_replica_read = ‘leader-and-follower’;
SET @@SESSION.tidb_mem_quota_query = 16073741824;
SET @@SESSION.group_concat_max_len = 102400;
SET @@SESSION.tidb_enable_paging = 1;
SET @@cte_max_recursion_depth = 11000;

使用命令:show variables like ‘%tidb_txn_mode%’; 查看一下是使用了哪个,悲观锁应该是pessimistic

执行select @@session.tidb_txn_mode,是pessimistic,没有问题

https://docs.pingcap.com/zh/tidb/stable/tidb-configuration-file#pessimistic-auto-commit

  • 用来控制开启全局悲观事务模式下 (tidb_txn_mode='pessimistic') 时,自动提交的事务使用的事务模式。默认情况下,即使开启全局悲观事务模式,自动提交事务依然使用乐观事务模式来执行。当开启该配置项后(设置为 true),在全局悲观事务模式下,自动提交事务将也使用悲观事务模式执行。行为与其他显式提交的悲观事务相同。

tidb的自动提交事务模型可以和设置的显式事务模型不同。而默认情况下,自动提交使用乐观事务,由上面文档连接中的参数控制。

不过写冲突怎么都存在,改成悲观事务,也就是从写冲突报错日志,变成了悲观锁等待。其实冲突还在,就是处理机制变了下。
必要的时候,为了数据库性能还是要把锁放在数据库外面。保证进库的时候不冲突。

比如使用redis/zookeeper之类的,来管理分布式锁。

懂了,我开启autocommit 主要是为了开启tidb_batch_insert,我刚看了看,batch-dml的做法已经被废弃了,目前是推荐使用 非事务 DML 语句 ,看来我需要考虑修改SQL了

额,非事务 DML 语句,也必须是autocommit,而且非事务DML的限制太多了,看来只能是开启事务后更新了

1 个赞

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