这里单说InnoDB引擎
实现事务,即实现事务的四大特性:___ ___ ___ ___
实现ACID核心依赖:
1.redo log【持久性】
- 修改数据的时候,不直接刷磁盘数据页,先把本次变更记录写到 redo log buffer;
- 事务提交时,把 redo log buffer 刷到磁盘上的 redo log 文件(持久化);(数据真正修改)
- 之后再慢慢刷脏页到数据文件(后台刷);
- 如果数据库宕机重启,扫描磁盘上已经落盘的 redo log,重做这些修改,把还没刷到数据页的变更恢复回来,保证提交成功的事务数据不丢失。
2.undo log【原子性】
- 事务修改数据前,先把该行修改前的旧数据写入 undo log ,同时行记录里的
roll_ptr指向这条 undo 记录; - 事务执行中如果触发 rollback,InnoDB 顺着
roll_ptr找到 undo log 里的旧版本,把旧数据写回原数据行; - 回滚完成后,undo log 不会立刻删除,放到undo 链表 ,供 MVCC 快照读继续使用,等没有事务再引用它才会被清理。
3.锁【一致性】 【隔离性】
很好理解
4.MVCC
实现读的隔离性
配合 undo log + Read View,让快照读可以读到某个一致性快照,不用加行锁,提升并发。
- undo log 存了一堆旧版本,连成版本链 比如一行数据被事务 A 改了、再被事务 B 改了,undo 里会保存它之前每一个样子,靠 roll_ptr 串起来,形成一条链表:最新记录 → 版本 1 → 版本 2 → ...
- Read View 是一个 "判断规则" Read View 里面存了:当前读这个快照的事务 ID、活跃事务 ID 列表、最小活跃 ID、最大 ID。 作用:用来判断版本链上的每一个版本,对我这个事务能不能看见。
- 读取逻辑 普通 select(快照读)的时候,InnoDB 拿着这个 Read View,顺着版本链从最新记录往 undo 旧版本挨个比对:
- 如果这个版本对当前事务可见 → 返回它
- 不可见 → 顺着 roll_ptr 去 undo 找上一个旧版本继续判断
5.事务 ID、行隐藏列(trx_id、roll_ptr)(是MVCC的底层基础【服务隔离性】)
trx_id:这条记录是哪个事务改的roll_ptr:指针,指向 undo log 里上一个旧版本 多个版本连起来 = 版本链
举个极简例子(RR)
事务 T1 开启,第一次普通 select,生成Read View
事务 T2 修改同一行并提交(当前读,加锁修改,生成新版本放到版本链头部)
T1 再 select:拿着最开始的 Read View 去版本链比对
T2 的新版本对 T1 不可见,就找到 undo 里 T2 修改前的旧版本返回。
👉 T1 两次读到一样的数据(可重复读),而且全程没加锁 ,T2 修改不受阻塞。
undo log 提供多个历史版本 ,Read View 提供可见性判断规则,两者配合,快照读不用加锁就能读到符合隔离级别的一致性数据,读写不冲突,提高并发。
四个事务隔离级别
事务的隔离级别以及对应的哪些问题会出现不会出现:...
区分:隔离级别、数据库范式、事务四大特性、并发读问题