# 分布式事务

__*分布式事务*__
__*Lock*__
__*Default*__
__*Write*__
__*start timestamp*__
__*commit timestamp*__
__*startTS*__
__*start_ts*__
__*commitTS*__
__*commit_st*__

![`smart`](PercolatorTiKV01_zh_001_20220511.png)
-------------------------------------------------------------
如果我们要同时操作多行数据,而这些数据属于不同的 `Region`（甚至可能在不同的 `TiKV` 节点上）,为了保证操作的一致性,我们就需要分布式事务。

分布式事务要解决的问题是,比如我们需要同时将 `< 1,Tom >` 改为 `< 1,Jack >`, `< 2,Andy >` 改为 `< 2, Candy >`, 而 `< 1,Tom >` 和 `< 2,Andy >` 存储在不同的 `Region` 甚至 `TiKV` 节点上, 那么当操作结束之后,有可能会出现, `< 1,Tom >` 改为 `< 1,Jack >` 成功, 但是 `< 2,Andy >` 改为 `< 2, Candy >` 失败或者反之。这样就破坏了事务的原子性。

`TiDB` 参考了 `Google` 的 `Percolator`, 对 `2PC`（两阶段提交）进行了优化, 来提供分布式事务支持:
- 整个数据库需要有一个全局唯一和单调递增的 `timestamp` 来标识事务的开始时间 `start timestamp (start_ts)` 和提交时间 `commit timestamp (commit_ts)`, 这个 `timestamp` 由 `PD` 提供。
- `Percolator` 使用了 `RocksDB` 实例中的三个`Column Family` 来存储数据、事务和锁信息。它们分别是: `Lock`, `Default` 和 `Write`。比如, 当我们写入 `< 3, Frank >`, 会将 `key = 3` 的锁记录到 `Lock CF` 中, 将值 `"3"` 和 `"Frank"` 放到 `Default CF` 中, 如果成功提交了, 会在 `Write CF` 中进行记录, 并删除掉锁的信息。