ACID分别如何实现
原子性(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实现,确保并发事务之间的隔离。
一致性依赖于其他三个特性,并结合数据库和应用层面的保障实现。