ACID是衡量事务的四个特性:

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

MySQL的事务是如何实现这个特性的呢?

持久性

持久性相对简单一点。Innodb为例。

定义

持久性是指事务一旦提交,它对数据库的改变是永久性的,如果出现故障也不会改变。

实现原理

Innodb引擎为了读写数据的效率,引入了一个叫做Buffer Pool的缓冲区,是对磁盘中一部分数据的映射,查询修改的时候会先对这个缓冲区就行操作,过一段时间后,会将修改刷入到磁盘。这样做的弊端是缓冲区还没刷新修改的时候,服务宕机,导致修改不能落盘,也就丢失了数据。
故使用redo log,当数据修改的时候,除了修改Buffer Pool,也在redo log中记录这个操作,当事务提交后,首先会对redolog刷盘,重启服务后,会读redolog,重做这个操作,保证数据不会丢失。wal(write-ahead logging)先写日志,再更新buffer pool,刷脏成功后,redlog也就没用了

redolog写入磁盘快:redolog每次都是追加日志,没有随机io,每次只刷修改部分,而不是整个16kb的页。

隔离性

定义

隔离性事务内部的操作与其他事务是隔离的,并发执行的事务也不应该相互影响。
主要分为两个方面:

  1. 一个事务的写操作对另一个事务写操作的影响(锁机制保证)
  2. 一个事务的写操作对另一个事务的读操作的影响(MVCC保证)

原理

锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

原子性

定义

原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。

原理

基于重做日志undo log实现,当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
undo log记录的是逻辑操作,是实际数据操作的反操作,比如insert语句,则会记上delete,回滚的时候,直接执行日志。

一致性

定义

一致性是指事务执行结束后,数据库的完整性不能有变化,比如:实体完整性、主键完整性、列完整性、外键约束等。

实现

实现一致性的措施包括:

  • 保证原子性、持久性和隔离性,如果这些特性无法保证,事务的一致性也无法保证
  • 数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等
  • 应用层面进行保障,业务逻辑要保证正确