事务与并发控制
最后更新: 2026-01-22
作者: MySQL Team
页面目录
第八章:事务与并发控制
8.1 事务基础
什么是事务
事务(Transaction)是一组原子性的 SQL 操作,要么全部执行成功,要么全部失败回滚。
ACID 特性
| 特性 | 说明 |
|---|---|
| Atomic(原子性) | 事务是最小执行单位,不可分割 |
| Consistency(一致性) | 事务执行前后,数据库状态保持一致 |
| Isolation(隔离性) | 并发执行的事务互不干扰 |
| Durability(持久性) | 事务提交后,结果永久保存 |
事务控制语句
-- 开始事务
START TRANSACTION;
-- 或
BEGIN;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- 设置保存点
SAVEPOINT savepoint_name;
-- 回滚到保存点
ROLLBACK TO SAVEPOINT savepoint_name;
-- 释放保存点
RELEASE SAVEPOINT savepoint_name;
事务示例
-- 示例:转账操作
START TRANSACTION;
-- 扣除转账人余额
UPDATE accounts SET balance = balance - 1000 WHERE user_id = 1;
-- 增加收款人余额
UPDATE accounts SET balance = balance + 1000 WHERE user_id = 2;
-- 检查是否成功
-- 如果成功
COMMIT;
-- 如果失败
-- ROLLBACK;
保存点示例
START TRANSACTION;
INSERT INTO orders (product_id, amount) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO orders (product_id, amount) VALUES (2, 200);
SAVEPOINT sp2;
-- 回滚到第一个保存点
ROLLBACK TO SAVEPOINT sp1;
-- 提交(只保留 sp1 之前的数据)
COMMIT;
8.2 隔离级别
隔离级别类型
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 |
| READ COMMITTED | 不可能 | 可能 | 可能 |
| REPEATABLE READ(默认) | 不可能 | 不可能 | 可能 |
| SERIALIZABLE | 不可能 | 不可能 | 不可能 |
设置隔离级别
-- 查看当前隔离级别
SELECT @@transaction_isolation;
-- 设置会话级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 设置全局级别
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
各隔离级别详解
-- READ UNCOMMITTED(读未提交)
-- 其他事务未提交的更改也能看到
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM accounts WHERE id = 1; -- 可能看到脏数据
-- READ COMMITTED(读已提交)
-- 只能看到已提交的数据
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- REPEATABLE READ(可重复读,默认)
-- 同一事务中多次读取结果一致
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- SERIALIZABLE(串行化)
-- 最高隔离级别,完全串行执行
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
8.3 锁机制
锁类型
| 锁类型 | 说明 | 作用范围 |
|---|---|---|
| 共享锁(S) | 允许并发读取 | 行/表 |
| 排他锁(X) | 独占写操作 | 行/表 |
| 意向共享锁(IS) | 准备获取共享锁 | 表 |
| 意向排他锁(IX) | 准备获取排他锁 | 表 |
行锁
-- 排他锁(阻止其他事务修改)
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-- 共享锁(允许其他事务读取)
SELECT * FROM orders WHERE id = 1 LOCK IN SHARE MODE;
表锁
-- 加读锁
LOCK TABLES orders READ;
-- 加写锁
LOCK TABLES orders WRITE;
-- 解锁
UNLOCK TABLES;
锁等待与超时
-- 查看锁信息
SHOW ENGINE INNODB STATUS;
-- 查看当前锁
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
-- 查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
-- 设置锁等待超时(毫秒)
SET innodb_lock_wait_timeout = 5;
死锁
-- MySQL 自动检测并回滚较小事务解决死锁
-- 查看死锁日志
SHOW ENGINE INNODB STATUS;
-- 死锁示例
-- 事务A: LOCK T1 -> LOCK T2
-- 事务B: LOCK T2 -> LOCK T1
-- 解决:回滚占用锁较少的事务
8.4 MVCC
什么是 MVCC
MVCC(Multi-Version Concurrency Control)多版本并发控制,通过保存数据的多个版本实现并发控制。
InnoDB MVCC 实现
-- 每行数据有两个隐藏列
-- DB_TRX_ID: 最后修改的事务ID
-- DB_ROLL_PTR: 指向undo log的指针
-- READ COMMITTED: 每次 SELECT 生成新快照
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 同一事务中,多次 SELECT 可能看到不同数据
-- REPEATABLE READ: 事务开始时生成快照
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 同一事务中,多次 SELECT 结果一致
快照读 vs 当前读
-- 快照读:普通 SELECT(读取快照)
SELECT * FROM orders;
-- 当前读:加锁读取(读取最新数据)
SELECT * FROM orders FOR UPDATE;
INSERT INTO orders VALUES (...);
UPDATE orders SET ...;
DELETE FROM orders WHERE ...;
8.5 事务使用建议
-- 建议1:尽量使用短事务
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- 立即提交
-- 建议2:避免长事务
-- 长事务占用锁资源时间长,增加死锁风险
-- 建议3:按固定顺序访问资源
-- 避免不同事务按不同顺序访问导致死锁
-- 建议4:使用合适的事务隔离级别
-- 业务需要高一致性用 SERIALIZABLE
-- 性能优先用 READ COMMITTED
-- 建议5:大事务拆分
START TRANSACTION;
-- 分批处理
COMMIT;
8.6 本章小结
✅ 事务:保证数据操作的原子性、一致性
✅ ACID:原子性、一致性、隔离性、持久性
✅ 隔离级别:READ UNCOMMITTED 到 SERIALIZABLE
✅ 锁机制:行锁、表锁、共享锁、排他锁
✅ MVCC:多版本并发控制,提高并发性能