悲观模式下写写冲突测试的疑问

【 TiDB 使用环境】线上、测试、调研
【 TiDB 版本】
【遇到的问题】

当前环境是悲观事务模式,为什么我下面的测试中,session2的事务提交了以后,session1的事务再提交会出现写写冲突的信息呢?


mysql> 
mysql> show variables like '%txn_mode%';
+---------------+-------------+
| Variable_name | Value       |
+---------------+-------------+
| tidb_txn_mode | PESSIMISTIC |
+---------------+-------------+
1 row in set (0.01 sec)


mysql> show create table zjp;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                      |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| zjp   | CREATE TABLE `zjp` (
  `id` int(11) NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

SESSION1: 开启事务
mysql>
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

SESSION2:更新id=13的记录
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update zjp set name=‘ABC’ where id=13;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

SESSION1:更新id=13的记录,后台日志报写冲突
mysql> update zjp set name=‘ABC’ where id=13;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0

tidb.log
[2022/08/09 10:57:24.191 +08:00] [INFO] [adapter.go:633] [“pessimistic write conflict, retry statement”] [conn=446] [txn=435162658714681346] [forUpdateTS=435162658714681346] [err=“[kv:9007]Write conflict, txnStartTS=435162658714681346, conflictStartTS=435162659501113346, conflictCommitTS=435162668178079745, key={tableID=534, handle=12} primary={tableID=534, handle=12} [try again later]”]

【复现路径】做过哪些操作出现的问题
【问题现象及影响】

【附件】

请提供各个组件的 version 信息,如 cdc/tikv,可通过执行 cdc version/tikv-server --version 获取。

你的什么版本,5.2.3上按你的步骤没复现

我的版本是4.0.16

  1. 较新的版本里 tidb.log 在debug日志级别可能才有这种write conflict记录
  2. tidb的悲观事务是在DML阶段上锁,即往tikv写入 lock info,在写入时会有冲突检测,检查是否有commit的事务commit_ts比当前事务的forupdatets大,大则返回write conflict信息,
    session1 开始事务的txnStartTS=435162658714681346 执行DML时forUpdateTS=435162658714681346,session2 提交后conflictCommitTS=435162668178079745 。sess 1 的forUpdateTS 小于sess2.CommitTS 所以报冲突
    3、 猜测 在悲观事务里会重新使用从pd获取ts作为forupdatets,然后检查执行SQL

下面是悲观锁加锁流程:

我感觉按照这个逻辑,业务比较繁忙的情况下,这个提示信息会很多,不知道是不是这样的。