04.TiDB MVCC常识原理
TiDB 和 MySQL 都使用 MVCC 来实现事务并发控制,但实现方式不同
TiDB 基于分布式架构,使用 RocksDB 和时间戳实现多版本存储,更适合大规模分布式场景
而 MySQL 依赖集中式的 undo log 和隐藏字段(如 DB_TRX_ID
)
TiDB 的 MVCC 通过时间戳选择历史版本,无需回滚日志,事务可见性也通过时间戳控制
TiDB 使用 2PC 保证分布式事务一致性,而 MySQL 基于锁机制管理事务并发
# 01.TiDB 中 MVCC 原理
# 0、概述
- TiDB 和 MySQL 都通过 MVCC 来实现事务并发控制,避免了锁机制对性能的影响
- 区别在于存储和实现方式:
- MySQL 使用 undo log 和隐藏字段来管理多版本
- 而 TiDB 直接通过时间戳和 RocksDB 的多版本存储来实现
- 分布式架构:
- TiDB 的 MVCC 是完全分布式的,基于时间戳的并发控制,更适合大规模分布式场景
- 而 MySQL 仍然是集中式架构下的实现
# 1、MVCC 的核心思想
- TiDB 使用 MVCC 来实现事务中的乐观并发控制,允许多个事务同时对数据库进行读写操作,避免冲突
- 每个事务在读取数据时,不会阻塞其他写操作
- 每次写入操作都会为数据生成一个新的版本,而读取操作则根据事务的时间戳决定读取哪个版本的数据
# 2、快照读与当前读
与 MySQL 类似,TiDB 也分为快照读和当前读
- 快照读:读取的是数据的某个历史版本,这个版本是基于事务开始时的快照,不需要加锁
- 当前读:读取的是最新的已提交版本,涉及到增删改操作,可能需要加锁来避免冲突
在 TiDB 中,默认的 SELECT
操作是快照读,而涉及到数据修改的操作(INSERT
、UPDATE
、DELETE
)则是当前读
# 3、多版本存储结构
TiDB 中,每条记录实际上存储多个版本
每个版本包含:
- Key:表示数据的主键
- Value:存储每个版本的数据值
- Timestamp:与每个版本关联的时间戳,由事务管理器(PD)生成的全局递增时间戳
当事务在进行写操作时,会为每次更新生成一个新版本,TiDB 会根据读取时的时间戳选择合适的版本进行返回
这通过快照机制实现了读写分离,避免了直接锁的使用
# 4、可见性规则
TiDB 通过时间戳(TSO)来决定事务读取的可见性
每个事务在开始时会获取一个逻辑时间戳,并使用它来确定哪些版本是可见的
- 当读取数据时,TiDB 会比较每个版本的时间戳,只读取那些在当前事务开始之前已存在的版本
- 如果发现该数据有比当前事务时间戳更新的版本,这些更新就会对该事务不可见,事务读取的仍是旧版本的数据
这与 MySQL 的 Read View
类似,用于确保事务读取的数据是符合一致性要求的
# 02.与 MySQL MVCC差异
# 1、隐藏字段
- MySQL:
- 在 InnoDB 引擎中,使用隐藏字段如
DB_TRX_ID
(记录最近修改该行的事务ID) - 和
DB_ROLL_PTR
(回滚指针)来实现多版本并发控制
- 在 InnoDB 引擎中,使用隐藏字段如
- TiDB:
- TiDB 并不直接存储
DB_TRX_ID
等字段,而是通过每次写入数据时附加一个时间戳 - 这个时间戳是通过 PD(Placement Driver)生成的唯一标识
- TiDB 并不直接存储
# 2、存储结构
- MySQL:
- 使用 undo log 和 redo log 来管理多版本
- 在快照读中,MySQL 通过 undo log 回滚到对应的历史版本来实现 MVCC
- TiDB:
- 使用 RocksDB 存储引擎,每条数据存储的多个版本会被物理上分布在不同的 TiKV 节点上,数据的历史版本通过时间戳区分
- TiDB 直接通过时间戳来选择历史版本,而不需要像 MySQL 那样通过 undo log 回滚
# 3、可见性判断
- MySQL:
- 通过
Read View
和活跃事务列表来判断某个事务是否可见 - MySQL 的
Read View
会维护一组当前活动的事务 ID 列表,来决定当前事务能看到哪些版本的数据
- 通过
- TiDB:
- 使用时间戳直接决定事务的可见性
- 当事务读取数据时,TiDB 会比较该版本的时间戳和当前事务的时间戳,以判断该数据是否对当前事务可见
# 4、事务模型
- MySQL:
- InnoDB 使用的是基于锁的事务管理模型
- 虽然 MVCC 实现了读写并发,但在需要当前读时,仍然会使用锁来保证数据一致性
- TiDB:
- TiDB 完全基于分布式事务模型,并使用 2PC(二阶段提交)来保证数据的一致性
- 在快照读中,不涉及锁机制,而是基于 MVCC 实现的时间戳版本控制
# 03.MVCC 的并发控制流程
# 1、MySQL 流程
- 事务开启时生成
Read View
,记录当前活跃事务列表 - 对每条读取的数据,判断该数据是否对当前事务可见
- 如果
DB_TRX_ID
小于或等于Read View
中的最小事务 ID,则数据可见 - 如果
DB_TRX_ID
在Read View
活跃事务列表中,则数据不可见,继续读取 undo log 找到合适版本
- 如果
- 对于修改操作,生成新的版本并更新
DB_TRX_ID
和DB_ROLL_PTR
# 2、TiDB 流程
- 事务开始时从 PD 获取全局唯一时间戳
- 读取数据时,TiDB 会选择所有小于当前事务时间戳的版本
- 每条数据的不同版本根据其时间戳存储在 TiKV 中,读取时直接根据时间戳筛选合适的版本
- 写操作时,TiDB 会为每次写入数据生成一个新的时间戳,并将新版本存储在 TiKV 中
上次更新: 2024/10/15 16:27:13