MySQL-事务

82 阅读3分钟

本篇讨论MySQL本身如何实现事务的ACID特性

如何保证原子性?

原子性:事务内的操作要么全成功或者全失败

  1. undo log 在DML操作时读取buffer pool的数据页,将数据页旧版本记录到表空间中,等事务发生错误或者显式回滚时,innodb利用undo log恢复到修改前的状态,保证全部执行或者全部不执行。
  2. 2PC两阶段提交 2PC指的是准备阶段、提交阶段。 redolog binlog都落盘,则准备阶段OK redo log写入commit record,修改事务状态为已提交,释放事务持有的所有行锁间隙锁

为什么要两阶段提交:保证redo log binlog的原子性。 redo log用于崩溃恢复 而binlog用于主从同步

如果redolog有修改但 binlog没有那么崩溃恢复后主库更改但从库无更改。

如果binlog有修改但主库没有修改,那么从库有更新,主库没有更新。

都会造成主从数据不一致,所以必须保证两个日志的原子性,要么全落盘,要么都不落。

如何保证一致性?

一致性:从一个满足完整性规则的状态切换到另一个也满足这些规则的状态

  1. 约束与触发器 主键约束,保证表中不会有重复数据 检查约束,保证表中数据合法 外键约束,保证子表中的外键对应的父表一定有记录,不会存在“悬空“或孤儿”记录 触发器保证操作不会被人为因素被跳过,只要被触发一定会执行触发器内的SQL 与DML操作同处一个事务上下文,如果出错会一起回滚,提交也是一起提交,保证了修改数据强制执行一致性逻辑,避免遗漏或部分生效

  2. 事务: 原子性和一致性相结合,要么全部执行,要么全部回滚。不会出现半执行的不一致状态 隔离级别与MVCC 通过MVCC、行锁、间隙锁防止读写过程中出现脏读、幻读、不可重复读等问题。 2PC 确保redo log binlog安全落盘不会出现主从数据不一致的状态

如何保证隔离性?

隔离性:并发事务互不影响,执行的效果如同串行执行

MVCC机制+锁(行锁,间隙锁,临键锁)

详见: juejin.cn/post/749671…

如何保证持久性?

持久性:事务一旦提交,修改就永久保留,即使系统崩溃也不会丢失

  • redo log + 刷盘机制 保证最近数据的改动持久化到日志文件中。
  • innodb的崩溃恢复机制,利用redo log的write指针的最新位置来将已提交事务持久化到磁盘。
  • 双写缓冲:防止极端场景导致数据页半页写入而损坏,先把脏页写入连续双写区域,再批量写入数据文件,崩溃恢复后用双写区恢复完整页。

详见:juejin.cn/post/750236…

参考

《高性能MySQL-第四版》

《极客时间-MySQL45讲》

《MySQL技术内幕-InnoDB存储引擎-第二版》