开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
背景
事务的特性(ACID)
- 原子性:通过 undo log 实现
- 一致性:原子性、隔离性、持久性保证了事务的一致性。
- 隔离性:通过锁和 MVCC 实现
- 持久性:通过 redo log 实现
并发事务带来的问题
- 脏读(Dirty read):事务A读取到事务B已经修改但未提交的数据。
- 不可重复读(Unrepeatable read):事务A两次读数据之间,事务B对该数据进行了修改
- 幻读(Phantom read):事务A两次读数据之间,事务B提交了新的数据。
事务的隔离级别
- 读未提交(READ-UNCOMMITTED)
- 读已提交(READ-COMMITTED)
- 可重复读(REPEATALBE-READ)
- 可串行化(SERIALIZABLE)
MVCC
MVCC(多版本并发控制):通过版本链来控制并发事务访问同一个记录。用来解决数据库读写时的线程安全问题,不抢占读写锁,采用的是快照读,可能会读到历史数据。
MVCC 基于 undo log,版本链,Read View 来实现。
Read View
Read View 有四个重要的字段:
- m_ids:创建 Read View 时,当前数据库中活跃事务(已启动但未提交的事务)的 id 列表
- min_trx_id:活跃事务列表中的最小 id
- max_trx_id:下一个将要被分配的事务 id,即全局事务中最大事务的 id + 1
- creator_trx_id:创建该 Read View 的事务 id
规则:
在访问某条记录时,根据 Read View 规则判断该记录的某版本是否可见
- trx_id == create_trx_id :可访问该版本的记录
- trx_id < min_trx_id:可访问该版本的记录
- trx_id > max_trx_id:不可访问该版本记录
- min_trx_id <= trx_id <= max_trx_id:若 trx_id 不在 m_ids 中,可访问,否则不可访问
MVCC 整体流程
- 首先获得自己的事务 ID
- 获取 Read View
- 查询最新数据,获取该数据的 trx_id,与 creator_trx_id 相比较
- 若不符合,根据 roll_pointer 查询 undo log 中的数据,继续根据 Read View 规则判断
- 最后返回符合规则的数据