在计算机科学,尤其是数据库和分布式系统 领域中,事务(Transaction) 是指由一系列数据库操作组成的、不可分割的逻辑工作单元。这些操作要么全部执行成功并永久生效,要么全部执行失败并回滚到初始状态,以此保证数据的一致性和可靠性。
事务的核心价值在于解决并发操作 和系统故障下的数据错乱问题,常见的应用场景包括银行转账、电商订单支付、机票预订等。
一、事务的核心特性(ACID 原则)
事务的四大特性被称为 ACID 原则,这是事务机制的基石,缺一不可。
1. 原子性(Atomicity)
核心定义:事务是一个不可分割的最小操作单元,事务中的所有操作要么全部执行成功,要么全部执行失败,不存在 "部分执行" 的中间状态。
- 成功场景 :事务内的所有 SQL 语句执行完毕且无错误,事务会被提交(Commit),所有修改会被永久保存到数据库。
- 失败场景 :事务中任意一步操作出错(比如语法错误、约束冲突、系统崩溃),事务会被回滚(Rollback),数据库会恢复到事务执行前的状态,就像这个事务从未执行过。
典型例子:银行转账,从账户 A 扣 100 元,向账户 B 加 100 元。
- 若两步都成功 → 事务提交,转账完成;
- 若扣钱成功但加钱失败 → 事务回滚,账户 A 的 100 元会被恢复,避免 "钱不翼而飞"。
2. 一致性(Consistency)
核心定义:事务执行前后,数据库的完整性约束和业务规则始终保持一致,数据从一个合法的状态转换到另一个合法的状态,不会出现中间的非法状态。
- 完整性约束包括:主键唯一、外键关联、字段非空、取值范围限制等;
- 业务规则包括:转账后两个账户的总金额不变、订单创建后库存数量相应减少等。
典型例子:转账前 A + B 总金额 = 2000 元 → 转账后 A + B 总金额 仍 = 2000 元,不会出现总额增加或减少的情况。
- 如果事务执行后总额改变,就违反了一致性。
3. 隔离性(Isolation)
核心定义:多个事务并发执行时,一个事务的执行不能被其他事务干扰,不同事务之间相互隔离,每个事务都感觉不到其他事务在并发执行。
- 并发事务的问题:脏读、不可重复读、幻读;
- 数据库通过设置隔离级别 来平衡隔离性和并发性能,常见隔离级别从低到高为:
- 读未提交(Read Uncommitted):最低级别,允许读取其他事务未提交的修改,会出现脏读、不可重复读、幻读;
- 读已提交(Read Committed):只能读取其他事务已提交的修改,解决脏读,仍存在不可重复读、幻读;
- 可重复读(Repeatable Read):事务执行期间多次读取同一数据,结果始终一致,解决脏读、不可重复读,仍存在幻读(MySQL InnoDB 默认级别);
- 串行化(Serializable):最高级别,事务串行执行,完全隔离,解决所有并发问题,但性能最差。
典型例子:事务 T1 读取数据 A = 100 → 事务 T2 修改 A = 200 但未提交 → 若隔离级别为读未提交,T1 会读到 A = 200(脏读);若为读已提交,T1 仍读 A = 100。
4. 持久性(Durability)
核心定义:一个事务一旦提交成功,其对数据库的修改就是永久性的,接下来的其他操作或系统故障都不会导致该修改丢失。
- 实现原理:事务提交时,数据库会将修改的数据从内存缓冲区刷写到磁盘的持久化存储中;
- 注意:持久性是相对的,极端的物理故障(比如磁盘彻底损坏)可能导致数据丢失,通常需要配合备份、容灾机制来保障。
典型例子:转账事务提交后,即使服务器立刻断电重启,账户 A 和 B 的金额修改也不会消失。
二、事务的分类
根据执行环境和管理方式,事务可分为以下几类:
- 本地事务:由单个数据库管理系统(DBMS)管理的事务,只涉及一个数据源,ACID 特性由 DBMS 直接保证,比如 MySQL 的单库事务。
- 分布式事务 :涉及多个不同数据源(比如多个数据库、消息队列、文件系统)的事务,需要协调多个资源管理器,常见协议有 2PC(两阶段提交)、3PC(三阶段提交)、TCC(补偿事务)、SAGA 等。
三、事务的实现关键技术
- 日志(Log) :数据库通过重做日志(Redo Log) 和回滚日志(Undo Log) 实现原子性和持久性。
- Redo Log:记录事务对数据的修改,用于故障恢复时重做已提交的事务;
- Undo Log:记录事务修改前的数据状态,用于事务回滚或一致性读。
- 锁机制(Lock):实现隔离性的核心,通过对数据加锁来防止并发事务的干扰,比如行锁、表锁、共享锁、排他锁。
- 多版本并发控制(MVCC):InnoDB 等存储引擎的核心技术,通过为数据生成多个版本,让不同事务读取不同版本的数据,避免加锁阻塞,提升并发性能。
四、事务的应用注意事项
- 事务的范围要尽量小:避免在事务中执行耗时操作(比如远程调用、文件读写),否则会占用数据库连接,降低并发性能。
- 避免长事务:长事务会持有锁的时间变长,容易引发死锁,还会导致 Undo Log 膨胀。
- 分布式事务的权衡:2PC 强一致性但性能差,TCC/SAGA 性能高但实现复杂,需根据业务场景选择。