trx_sys->next_trx_id_or_no 保存的是下一个事务 ID 或事务提交号,具体是哪个,取决于是生成事务 ID 还是生成事务提交号先调用 trx_sys_allocate_trx_id_or_no() 。
也就是说,事务 ID 和事务提交号是同一条流水线上生产出来的 。我们以 trx 1 和 trx 2 两个事务为例,来说明生成事务 ID 和事务提交号的流程 。
假设此时 trx_sys->next_trx_id_or_no 的值为 100,trx 1、trx 2 启动和提交的顺序如下:
- trx 1 启动 。
- trx 2 启动 。
- trx 1 提交 。
- trx 2 提交 。
- trx 1 生成事务 ID,得到 100 。trx_sys->next_trx_id_or_no 加 1 , 结果为 101 。
- trx 2 生成事务 ID , 得到 101 。trx_sys->next_trx_id_or_no 加 1,结果为 102 。
- trx 1 生成事务提交号,得到 102 。trx_sys->next_trx_id_or_no 加 1,结果为 103 。
- trx 2 生成事务提交号,得到 103 。trx_sys->next_trx_id_or_no 加 1,结果为 104 。
2.3 修改 update undo 段状态如果事务更新或删除了用户普通表的记录,InnoDB 会为事务分配一个 update undo 段 。
如果事务更新或删除了用户临时表的记录,InnoDB 会为事务分配另一个 update undo 段 。
InnoDB 可能会给事务分配 0 ~ 2 个 update undo 段 。commit 子阶段会修改分配给事务的所有 update undo 段的状态 。
如果 update undo 段满足缓存条件 , 它的状态会被修改为 TRX_UNDO_CACHED,否则,它的状态会被修改为 TRX_UNDO_TO_PURGE 。
2.4 undo 日志组加入 history list修改完 update undo 段的状态,update undo 段的 undo 日志组会加入回滚段的 history list 链表 。purge 线程会从这个链表中获取要清理的 undo 日志组 。
前面已经生成了事务提交号,这里会把事务提交号写入 undo 日志组的头信息中 。
如果 update undo 段的状态为 TRX_UNDO_CACHED , 表示这个 undo 段需要缓存起来 。它会加入回滚段的 update_undo_cached 链表头部 , 以备后续其它事务需要 update undo 段时,能够快速分配 。
3. InnoDB 提交事务完成前面的一系列操作完成之后,InnoDB 提交事务的操作就完成了 。
现在,要把事务状态修改为 TRX_STATE_COMMITTED_IN_MEMORY 。
修改之后,新启动的事务就能看到该事务插入或更新的记录,看不到当前事务删除的记录 。
接下来,InnoDB 会释放事务执行过程中加的表锁、记录锁 。
释放锁之后,还要处理 insert undo 段 。
如果 insert undo 段的状态为 TRX_UNDO_CACHED,表示这个 undo 段需要缓存起来 。它会加入回滚段的 insert_undo_cached 链表头部,以备后续其它事物需要 insert undo 段时,能够快速分配 。
如果 insert undo 段的状态为 TRX_UNDO_TO_FREE , 它会被释放,占用的 undo 页会还给 undo 表空间 。
二阶段提交的 flush 子阶段,已经把 prepare 阶段及之前产生的 redo 日志都刷盘了 。
commit 子阶段,修改 insert undo 段和 update undo 段的状态 , 还会产生 redo 日志 。
InnoDB 不会主动触发操作系统把这些 redo 日志刷盘,而是由操作系统决定什么时候把这些 redo 日志刷盘 。
InnoDB 敢这么做,是因为这些 redo 日志对于确定事务状态已经不重要了 。即使这些 redo 日志刷盘之前 , 服务器突然异常关机,导致 undo 段的状态丢失 。MySQL 下次启动时 , 也能正确的识别到事务已经提交完成了 。
4. 重新初始化事务对象到这里,InnoDB 提交事务该做的操作都已经做完了 。提交事务完成之后,该做的事也都做了 。
对于上一个事务 , 事务对象的使命已经结束 。这里会把事务状态修改为 TRX_STATE_NOT_STARTED 。
事务对象也会被重新初始化,但是它不会被释放 。也就是说,事务对象不会回到事务池中 , 而是留给当前连接后续启动新事务时复用 。
5. 总结InnoDB 提交事务,就像我们填完一个表格之后,最后盖上的那个戳,总体上来说,要干 3 件事 。
第 1 件,修改分配给事务的各 undo 段的状态 。
推荐阅读
- 东航坠机事故,你关心的十大核心问题是什么
- ie浏览器一直弹出修复工具,QQ浏览器怎么设置漏洞模块拦截
- 十八项核心制度闭环管理是什么意思 十八项核心制度闭环管理是什么意思呀
- 从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
- 功率模块自热阻和耦合热阻区别 功率模块自热阻和耦合热阻区别是什么
- 准线上事故之MySQL优化器索引选错
- 什么是网络中的路由器?核心功能解释
- MySQL数据恢复,你会吗?
- 揭秘Sora技术路线:核心成员来自伯克利,基础论文曾被CVPR拒稿
- 如何在MySQL中实现数据的版本管理和回滚操作?