事务ACID特性

事务是一组原子性的SQL查询,一个独立的工作单元。如果数据库引擎能够成功对数据库应用该组查询的全部语句,那么就执行该组查询。如果其中任何一条因为崩溃或其他原因无法执行,那么所有的语句都不会被执行。事务内的语句,要么全部执行成功,要么全部执行失败。[1]

  1. 原子性(atomicity)

    一个事务必须被视为一个不可分割的最小单元。[2]

    整个事务中所有的操作要么全部提交(成功),要么全部回滚(失败)。

    对于单一事务而言,不可能只执行其中的一部分操作。

  2. 一致性(consistency)

    总是从一个一致的状态转换到另一个一致的状态。[3]

    若在事务执行过程中系统崩溃,因事务的修改还未提交,事务的修改不会被保存。

  3. 隔离性(isolation)

    一个事务所做的修改在提交前,对于其他的事务是不可见的。[4]

    是否可见与**隔离级别(Isolation level)**相关。[5]

  4. 持久性(durability)

    一旦事务提交,修改将永久保存。即使系统崩溃修改的数据也不会丢失。[6]

    持久性的表现与持久性级别相关。

实现以上特性能提供更高的安全性,但也会需要数据库做更多的额外工作。[7]


  1. PostgreSQL 官方文档《Transactions》把事务描述为把多个步骤捆成一个 all-or-nothing 操作:中间状态不会被其他并发事务看见,若失败导致事务不能完成,则这些步骤不会影响数据库。参见 https://www.postgresql.org/docs/current/tutorial-transactions.html↩︎

  2. PostgreSQL《Transactions》进一步说明,事务从其他事务视角看要么完整发生,要么完全不发生,这就是 atomic 语义;MySQL 8.4《InnoDB and the ACID Model》也把 atomicity 定义为事务中语句作为不可分割单元运行。参见 https://www.postgresql.org/docs/current/tutorial-transactions.htmlhttps://dev.mysql.com/doc/refman/8.4/en/mysql-acid.html↩︎

  3. MySQL 8.4《InnoDB and the ACID Model》把 consistency 描述为保护数据免受崩溃影响的机制与数据库状态要求;工程上通常还需要把业务规则显式落到约束、状态条件或应用逻辑里,事务本身不会自动理解未表达的业务不变量:https://dev.mysql.com/doc/refman/8.4/en/mysql-acid.html↩︎

  4. PostgreSQL《Transactions》说明,打开事务中的已执行更新在事务完成前对其他事务不可见,提交后才作为一个整体对其他会话可见:https://www.postgresql.org/docs/current/tutorial-transactions.html↩︎

  5. PostgreSQL《Transaction Isolation》列出 SQL 标准隔离级别及 dirty read、nonrepeatable read、phantom read、serialization anomaly 等并发现象,并说明 PostgreSQL 的默认隔离级别是 Read Committed:https://www.postgresql.org/docs/current/transaction-iso.html↩︎

  6. PostgreSQL《Transactions》说明事务完成并被数据库确认后,更新会记录到永久存储;《Write-Ahead Logging (WAL)》进一步说明 WAL 通过先写日志再写数据页来支撑崩溃恢复。参见 https://www.postgresql.org/docs/current/tutorial-transactions.htmlhttps://www.postgresql.org/docs/current/wal-intro.html↩︎

  7. MySQL 8.4《InnoDB and the ACID Model》把 ACID 与可靠性、崩溃恢复、日志刷盘、存储设备缓存和配置项联系起来讨论,也提示可靠性、性能与配置之间存在工程取舍:https://dev.mysql.com/doc/refman/8.4/en/mysql-acid.html↩︎