TiDB 是一个兼容 MySQL 协议的分布式数据库,其核心能力之一就是:在分布式环境中实现强一致事务(ACID)
这篇文章我们不讲“是什么”,而是做一次手术级拆解:从一条 SQL 开始,一层层剖开 TiDB 事务的执行过程。
一、整体架构速览(先有全局观)
TiDB 的事务涉及三个核心组件:
- TiDB Server(SQL 层)
- PD(Placement Driver,调度+时间戳)
- TiKV(分布式 KV 存储)
核心思想:
SQL → Key-Value → 分布式事务(2PC + MVCC)
二、从一条 SQL 开始
假设你执行:
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
COMMIT;
这是一个典型的转账事务
三、事务执行的“解剖分层”
我们按时间顺序拆解:
阶段 1:获取时间戳(TSO)
事务开始时:
BEGIN;
TiDB 会向 PD 请求一个全局递增时间戳(TSO)
这个时间戳叫:Start TS
作用:
- 标识事务开始时间
- 实现 MVCC 可见性判断
阶段 2:SQL → KV 映射
例如:
UPDATE account SET balance = balance - 100 WHERE id = 1;
会被转换为:
Key: account:1:balance
Value: 新值
TiDB 是:
SQL 层 → 编译 → 执行计划 → 下推到 TiKV(KV 操作)
阶段 3:预写(Prewrite 阶段)【2PC 第一阶段】
这是整个事务最关键的一步。
做什么?
TiDB 会对所有修改的 key 执行:
Prewrite(预写)
写入内容包括:
- Lock(锁)
- Value(新值)
- Start TS
重点:Primary Key & Secondary Key
在所有 key 中:
- 选一个作为 Primary Key
- 其他是 Secondary Keys
Primary Key 决定事务成败!
举个例子:
Key1(id=1)→ Primary
Key2(id=2)→ Secondary
阶段 4:提交(Commit 阶段)【2PC 第二阶段】
Step 1:获取 Commit TS
TiDB 再次向 PD 请求时间戳:
Commit TS
必须满足:
Commit TS > Start TS
Step 2:提交 Primary Key
commit(primary key)
一旦 Primary 提交成功:
整个事务就“逻辑成功”了
Step 3:异步提交 Secondary Keys
commit(secondary keys)
这里是异步的(性能优化)
四、核心机制拆解
1. 两阶段提交(2PC)
TiDB 使用标准:
Two-Phase Commit
阶段 1:Prewrite
- 写锁 + 写数据(未提交)
阶段 2:Commit
- 写 commit 标记
2. MVCC(多版本并发控制)
TiDB 的数据结构:
Key + StartTS → Value
Key + CommitTS → 可见版本
查询时:
SELECT * FROM account;
会读取:
CommitTS ≤ 当前读时间戳的最新版本
3. Snapshot Isolation(快照隔离)
TiDB 默认隔离级别:
SI(类似 MySQL RR)
特点:
- 读不阻塞写
- 写不阻塞读
- 避免脏读、不可重复读
4. 乐观事务 vs 悲观事务
乐观事务(默认早期版本)
BEGIN;
-- 不加锁
COMMIT 时冲突检测
优点:快
缺点:冲突重试多
悲观事务(推荐)
BEGIN PESSIMISTIC;
SELECT ... FOR UPDATE;
优点:减少冲突
缺点:有锁等待
五、一次完整事务的时间线(总结版)
BEGIN
↓
获取 Start TS(PD)
↓
执行 SQL(缓存修改)
↓
Prewrite(写锁 + 数据)
↓
获取 Commit TS(PD)
↓
Commit Primary
↓
Commit Secondary(异步)
↓
结束
六、为什么 TiDB 能保证强一致?
关键在三个点:
1. 全局时间戳(PD)
- 单调递增
- 全局唯一
保证事务顺序一致
2. Raft 协议(TiKV)
- 每个 Region 使用 Raft
- 多副本一致性
保证数据可靠
3. 2PC + MVCC
- 事务原子性(2PC)
- 并发读写(MVCC)
七、常见问题(深入理解)
1:如果 Primary commit 成功,Secondary 失败?
事务仍然成功
TiDB 会通过:
- 后台重试
- 或读取时修复(resolve lock)
2:锁冲突怎么处理?
- 悲观事务 → 等锁
- 乐观事务 → 重试
3:长事务有什么问题?
会导致:
- GC 无法回收旧版本
- 性能下降
八、一张“脑图式总结”
SQL
↓
TiDB(解析 + 优化)
↓
KV 操作
↓
TiKV(分布式存储)
↓
2PC(Prewrite + Commit)
↓
MVCC(多版本)
↓
Raft(复制)
↓
一致性保证
九、结尾:一句话理解 TiDB 事务 TiDB 的本质:
用 时间戳 + KV + 2PC + Raft在分布式系统中“模拟单机数据库的事务体验”