Skip to content

MySQL 事务与锁机制

TIP

事务保证了一组数据库操作要么全部成功要么全部回滚。理解事务隔离级别和锁机制对避免数据不一致至关重要。

ACID 特性

特性说明
Atomicity(原子性)事务内的操作要么全做,要么全不做
Consistency(一致性)事务前后数据完整性约束不变
Isolation(隔离性)并发事务互不干扰
Durability(持久性)提交后数据永久保存

事务操作

sql
-- 开启事务
START TRANSACTION;

-- 业务操作
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;

-- 提交(成功)
COMMIT;

-- 回滚(失败)
ROLLBACK;

-- 设置保存点
SAVEPOINT sp1;
ROLLBACK TO sp1;

隔离级别

sql
-- 查看当前隔离级别
SELECT @@transaction_isolation;

-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
隔离级别脏读不可重复读幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ(默认)
SERIALIZABLE

行锁与表锁

sql
-- 行级锁:InnoDB 默认
-- ❌ 不走索引会导致行锁升级为表锁
UPDATE user SET age = 20 WHERE name = '张三'; -- name 无索引 → 表锁

-- 表级锁:手动加锁
LOCK TABLES user READ;
LOCK TABLES user WRITE;
UNLOCK TABLES;

-- 间隙锁(Gap Lock):REPEATABLE READ 级别防止幻读

死锁

java
// 死锁示例
// 事务A:UPDATE account SET balance=100 WHERE id=1;
// 事务B:UPDATE account SET balance=200 WHERE id=2;
// 事务A:UPDATE account SET balance=100 WHERE id=2;  -- 等待 B
// 事务B:UPDATE account SET balance=200 WHERE id=1;  -- 等待 A
// MySQL 会自动检测并回滚其中一个事务

// 避免死锁:
// 1. 按固定顺序访问资源
// 2. 尽量缩短事务时间
// 3. 减少锁的持有时间

MVCC(多版本并发控制)

InnoDB 通过 MVCC 实现非阻塞读:

- 每行记录保存多个版本
- 每个事务看到的是数据的快照(undo log)
- 实现 READ COMMITTED 和 REPEATABLE READ