目录
1. 认识事务
1.1. 什么是数据库事务
事务是访问数据库的程序执行单元;事务中可能包含一个或多个 SQL
语句,这些语句要么都执行,要么都不执行。事务的定义有几点需要解释下
- 数据库事务可以包含一个或多个
SQL
语句,这些操作构成一个逻辑上的整体 - 构成逻辑整体的这些数据库操作,要么全部执行成功,要么全部不执行
- 构成事务的所有操作,要么全都对数据库产生影响,要么全都不产生影响,即不管事务是否执行成功,数据库总能保持一致性状态
- 以上即使在数据库出现故障以及并发事务存在的情况下依然成立
1.2. 为什么需要数据库事务
转账是生活中常见的操作,比如从 A
账户转账 100
元到 B
账号。站在用户角度而言,这是一个逻辑上的单一操作,然而在数据库系统中,至少会分成两个步骤来完成
- 将
A
账户的金额减少100
元 - 将
B
账户的金额增加100
元
在这个过程中可能会出现以下问题
- 转账操作的第一步执行成功,
A
账户上的钱减少了100
元,但是第二步执行失败或者未执行便发生系统崩溃,导致B
账户并没有相应增加100
元 - 转账操作刚完成就发生系统崩溃,系统重启恢复时丢失了崩溃前的转账记录
- 同时又另一个用户转账给
B
账户,由于同时对B
账户进行操作,导致B
账户金额出现异常
为了便于解决这些问题,需要引入数据库事务的概念
1.3. 数据库事务的特性
- 原子性(
Atomicity
):事务中的所有操作作为一个整体像原子一样不可分割,要么全部成功,要么全部失败 - 一致性(
Consistency
):事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态 - 隔离性(
Isolation
):并发执行的事务不会相互影响,其对数据库的影响和它们串行执行时一样。比如多个用户同时往一个账户转账,最后账户的结果应该和他们按先后次序转账的结果一样 - 持久性(
Durability
):事务一旦提交,其对数据库的更新就是持久的。任何事务或系统故障都不会导致数据丢失
按照严格的标准,只有同时满足 ACID
特性才是事务;但是在各大数据库厂商的实现中,真正满足 ACID
的事务少之又少。例如 MySQL
的 NDB Cluster
事务不满足持久性和隔离性;InnoDB
默认事务隔离级别是可重复读,不满足隔离性;Oracle
默认的事务隔离级别为 READ COMMITTED
,不满足隔离性……因此与其说 ACID
是事务必须满足的条件,不如说它们是衡量事务的四个维度
2. 数据库事务特性的实现原理
在说明原子性原理之前,首先介绍一下 MySQL
的事务日志。MySQL
的日志有很多种,如二进制日志、错误日志、查询日志、慢查询日志等,此外 InnoDB
存储引擎还提供了两种事务日志:redo log
([riːˈduː]
重做日志)和 undo log
([ʌnˈduː]
回滚日志)。其中 redo log
用于保证事务持久性;undo log
则是事务原子性和隔离性实现的基础