事务与并发控制

最后更新: 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:多版本并发控制,提高并发性能