如何实现数据库的ACID

473 阅读3分钟

原子性

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

实现原理

  • 原子性说明事务执行失败,必须要进行回滚操作
  • undo log: InnoDB实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子

持久性

  • 持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

实现原理

  • 持久性说明需要写入到磁盘中,这里用的是 redolog 和 binlog 的两阶段提交实现

隔离性

  • 与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响

  • 隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。

实现原理

  • (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性

  • (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性

一致性

  • 一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。数据库的完整性约束包括但不限于: 实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。

实现原理

  • 首先:一致性是事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性

  • 其次:再mysql层面也需要对于一致性进行保证,比如说例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等

  • 最后: 应用层进行一致性的保护, 例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致

总结

  • 原子性:语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log

  • 持久性:保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log

  • 隔离性:保证事务执行尽可能不受其他事务影响;InnoDB默认的隔离级别是RR,RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)

  • 一致性:事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的

参考