背景
在 v6.0.0 版本,针对悲观事务引入了内存悲观锁的优化(In-memory lock),从压测数据来看,带来的性能提升非常明显(Sysbench 工具压测 oltp_write_only 脚本)。
- Tps 提升 30% 左右
- 减少 Latency 在 15% 左右
TiDB 事务模型从最初的乐观事务到悲观事务;在悲观事务上,又针对悲观锁进行的 ”Pipelined 写入“ 和 ”In-memory lock“ 优化,从功能特性上可以看出演进过程(参考TiDB 事务概览)。
乐观事务
乐观事务在提交时,可能因为并发写造成写写冲突,不同设置会出现以下两种不同的现象:
- 关闭乐观事务重试,事务提交失败:也就是执行 DML 成功(不会被阻塞),但是在执行 commit 时候失败,表现出与 MySQL 等数据库不兼容的行为。
| T1 | T2 | 说明 |
|---|---|---|
| mysql> set session tidb_disable_txn_auto_retry = 1(或者 set session tidb_retry_limit=0;);Query OK, 0 rows affected (0.00 sec) | 关闭重试 | |
| mysql> begin;Query OK, 0 rows affected (0.00 sec) | mysql> begin optimistic;Query OK, 0 rows affected (0.00 sec) | T2开启乐观事务 |
| mysql> delete from t where id = 1;Query OK, 1 row affected (0.00 sec) | ||
| mysql> delete from t where id = 1;Query OK, 1 row affected (0.00 sec) | 语句执行成功,没有被 T1 阻塞,跟 MySQL 行为不兼容 | |
| mysql> commit;Query OK, 0 rows affected (0.00 sec) | T1 提交成功 | |
| mysql> commit;ERROR 9007 (HY000): … | T2 提交失败 |
T2 事务提交失败,具体的报错信息如下:
mysql> commit;
ERROR 9007 (HY000): Write conflict, txnStartTS=433599424403603460, conflictStartTS=433599425871872005, conflictCommitTS=433599429279744001, key={tableID=5623, handle=1} primary={tableID=5623, handle=1} [try again later]
- 开启乐观事务重试,自动重试后返回成功,但是因为重试 DML 使用的事务 id(start_ts) 是重新获取的,不是事务开始的事务 id(start_ts),也就是说实际执行结果相当于同一个事务中读和写是使用不同的事务 id(start_ts),执行结果可能跟预期不一致。
| T1 | T2 | 说明 |
|---|---|---|
| mysql> set session tidb_disable_txn_auto_retry = 0;Query OK, 0 rows affected (0.00 sec) | 开启重试 | |
| mysql> set session tidb_retry_limit = 10;Query OK, 0 rows affected (0.00 sec) | 设置最大重试次数 | |
| mysql> begin;Query OK, 0 rows affected (0.00 sec) | mysql> begin optimistic;Query OK, 0 rows affected (0.00 sec) | T2开启乐观事务 |
| mysql> delete from t wh |

本文介绍了TiDB 6.0.0中引入的内存悲观锁优化,提升了TPS约30%和Latency约15%,讨论了乐观事务与悲观事务的差异,以及pipelined写入和in-memorylock的优化原理。重点强调了内存锁的局限性、锁丢失影响和适用场景,以及如何根据业务需求选择是否启用这些特性。
最低0.47元/天 解锁文章
869

被折叠的 条评论
为什么被折叠?



