原子性(Atomicity)
定义:事务是一个不可分割的工作单位,其中的操作要么全部执行,要么全部不执行。
实现原理:基于undo log(回滚日志)。当事务对数据库进行修改时,InnoDB 会生成对应的 undo log。如果事务执行失败或调用
rollback,InnoDB 会利用 undo log 中的信息将数据回滚到修改之前的状态。undo log 记录了 SQL 执行的相关信息,包括被修改行的主键、修改的列以及修改前后的值等,回滚时根据这些信息执行与之前相反的操作。
持久性(Durability)
定义:事务一旦提交,其对数据库的改变应该是永久性的,即使在系统故障或宕机的情况下也不会丢失。
实现原理:基于redo log(重做日志)。当数据修改时,除了修改 Buffer Pool 中的数据,还会在 redo log 中记录这次操作。事务提交时,会调用
fsync接口将 redo log 刷盘。如果 MySQL 宕机,重启时可以通过读取 redo log 中的数据对数据库进行恢复。redo log 采用 WAL(Write-ahead logging,预写式日志)机制,即先写日志再更新数据,保证数据不会因 MySQL 宕机而丢失。
隔离性(Isolation)
定义:并发执行的事务之间不能互相干扰,事务内部的操作与其他事务隔离。
实现原理:
锁:通过锁机制保证不同事务之间的写操作不会冲突。InnoDB 支持行锁和表锁,行锁的粒度更细,性能更好。事务在修改数据之前需要先获得相应的锁,锁定的数据在事务提交或回滚之前不会被其他事务修改。
MVCC(多版本并发控制):用于解决写操作对读操作的影响。MVCC 通过以下技术实现:
- 隐藏列:每行数据包含隐藏列,记录事务 id 和指向 undo log 的指针。
- 版本链:通过 undo log 形成版本链,记录数据的多个版本。
- ReadView:事务在读取数据时生成 ReadView,根据 ReadView 判断数据的可见性。ReadView 包含以下内容:
- low_limit_id:生成 ReadView 时系统中下一个事务的 id,大于等于此 id 的事务对 ReadView 不可见。
- up_limit_id:生成 ReadView 时系统中活跃事务的最小 id,小于此 id 的事务对 ReadView 可见。
- rw_trx_ids:活跃事务的 id 列表,用于判断事务是否在 ReadView 生成时活跃。
一致性(Consistency)
定义:事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。
实现原理:
依赖原子性、持久性和隔离性:这三者是实现一致性的基础。如果事务的原子性、持久性和隔离性无法保证,一致性也无法保证。
数据库层面的保障:数据库本身提供数据类型、长度、外键约束等完整性检查。
应用层面的保障:应用逻辑需要保证事务的逻辑一致性,例如转账操作中,扣除和增加金额的逻辑必须正确。
总结
原子性通过undo log实现,确保事务的不可分割性。
持久性通过redo log实现,确保事务提交后数据不会丢失。
隔离性通过锁机制和MVCC实现,确保并发事务之间的隔离。
一致性依赖于其他三个特性,并结合数据库和应用层面的保障实现。