事务基础与 ACID
约 1149 字大约 4 分钟
布欧-Lewyon
2026-05-15
首页 › MySQL › 事务与锁(在新窗口打开) › 事务基础与 ACID
事务(Transaction)是数据库管理系统执行过程中的一个逻辑单位,由一个或多个 SQL 语句组成。事务保证这组操作要么全部成功,要么全部失败。
事务的基本操作
-- 创建测试表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
balance DECIMAL(10, 2)
);
INSERT INTO account (name, balance) VALUES ('张三', 1000), ('李四', 1000);
-- 手工事务示例:张三转 200 给李四
START TRANSACTION; -- 标记事务开始
UPDATE account SET balance = balance - 200 WHERE name = '张三';
UPDATE account SET balance = balance + 200 WHERE name = '李四';
COMMIT; -- 提交事务(两行都生效)
-- 如果中间出错,可以回滚
START TRANSACTION;
UPDATE account SET balance = balance - 200 WHERE name = '张三';
-- 服务器断电、程序崩溃...
ROLLBACK; -- 回滚,张三余额不变SAVEPOINT(保存点)
允许部分回滚,而不影响整个事务:
START TRANSACTION;
INSERT INTO log VALUES ('操作1');
SAVEPOINT sp1; -- 设置保存点
INSERT INTO log VALUES ('操作2');
SAVEPOINT sp2;
INSERT INTO log VALUES ('操作3');
ROLLBACK TO SAVEPOINT sp2; -- 回滚到 sp2,操作3 被撤销
-- sp1 及之前还在,sp2 之后回滚
COMMIT; -- 提交保留的操作(操作1 和 操作2)隐式提交
-- DDL 语句会自动提交当前事务
START TRANSACTION;
INSERT INTO user VALUES (1, '张三');
CREATE TABLE temp (id INT); -- 隐式提交了 INSERT
ROLLBACK; -- INSERT 已被提交,无法回滚ACID 特性
A —— 原子性(Atomicity)
事务中的所有操作要么全部完成,要么全部不做。如果执行中途失败,通过 Undo Log 回滚到事务开始前的状态。
START TRANSACTION;
UPDATE account SET balance = balance - 200 WHERE id = 1;
-- 服务器崩溃...重启后
-- MySQL 通过 Undo Log 回滚这条 UPDATE,张三仍是 1000C —— 一致性(Consistency)
事务开始前和结束后,数据库的完整性没有被破坏。一致性本质上由其他三个特性共同保证,外加业务层的约束定义。
- 原子性保证操作全部或全不
- 隔离性保证并发不破坏一致
- 持久性保证提交后结果不丢失
I —— 隔离性(Isolation)
多个事务并发执行时,彼此之间应该互不干扰。隔离级别决定了允许出现的数据现象(脏读、不可重复读、幻读),详情见下一节。
D —— 持久性(Durability)
一旦事务提交,其结果就是永久的。即使提交后系统崩溃,重启后数据仍在。
实现机制:Redo Log(重做日志)
关键点:
- Redo Log 是顺序写(比数据文件的随机写快得多)。
- 提交事务时只需 Redo Log 刷盘,数据文件不必马上刷。
- 崩溃后 MySQL 重启时,用 Redo Log 重放尚未刷盘的操作。
REDO LOG 的关键参数
# 控制 Redo Log 刷盘策略
innodb_flush_log_at_trx_commit = 1 # 每次提交都刷盘(最安全)
# innodb_flush_log_at_trx_commit = 2 # 每秒刷盘(性能稍好,丢失 1 秒数据)
# innodb_flush_log_at_trx_commit = 0 # 由系统自动刷(最快,崩溃丢失 1 秒数据)
# Redo Log 文件大小
innodb_log_file_size = 512M
innodb_log_files_in_group = 3生产环境始终设置
innodb_flush_log_at_trx_commit = 1,事务持久性不应妥协。
AUTOCOMMIT
MySQL 默认开启自动提交(每条 DML 语句单独作为一个事务):
-- 查看当前状态
SHOW VARIABLES LIKE 'autocommit'; -- 默认 ON
-- 关闭自动提交
SET AUTOCOMMIT = 0;
-- 之后所有 SQL 都在一个事务中,直到显式 COMMIT 或 ROLLBACK事务的并发问题
| 问题 | 描述 | 是否允许(默认 RR) |
|---|---|---|
| 脏读 | 读到其他事务未提交的数据 | ❌ |
| 不可重复读 | 同一事务内两次读同一行,结果不同 | ❌ |
| 幻读 | 同一事务内两次范围查询,行数不同 | ❌(InnoDB RR 下) |
具体机制和隔离级别见下一节。
小结
- 事务将多步操作确保原子性:
START TRANSACTION→ 操作 →COMMIT/ROLLBACK。 - ACID:原子性(Undo Log)、一致性、隔离性(MVCC + 锁)、持久性(Redo Log)。
- Redo Log 是"先写日志再写数据"(WAL),保证持久性且性能可控。
innodb_flush_log_at_trx_commit = 1是生产环境的安全选择。
上一节:SQL 优化实战 下一节:隔离级别与 MVCC
