MySQL 事务与锁机制深入剖析

MySQL 事务与锁机制深入剖析

MySQL 事务和锁是保证数据一致性的核心机制,也是面试高频考点,更是实际开发中死锁、性能问题的根源所在。本文从原理到实践,帮你彻底搞懂 MySQL 的事务和锁。

一、ACID 特性详解

  • 原子性(Atomicity):事务内的操作要么全部成功,要么全部回滚。由 undo log 保证。
  • 一致性(Consistency):事务执行前后数据库处于合法状态,是事务的最终目标。
  • 隔离性(Isolation):多个事务并发执行时互不干扰。由 MVCC + 锁实现。
  • 持久性(Durability):事务提交后数据永久保存。由 redo log 和刷盘策略保证。

二、四种隔离级别与问题

隔离级别 脏读 不可重复读 幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ(默认) 部分解决
SERIALIZABLE

InnoDB 默认使用 REPEATABLE READ,并通过 Next-Key Lock 解决大多数幻读问题。

三、MVCC 多版本并发控制

MVCC 让读写操作互不阻塞。核心机制:

  • 每行数据有隐藏字段:trx_id(最后修改事务ID)和 roll_pointer(undo log 指针)
  • 每个事务开始时创建 Read View(一致性视图),记录当前活跃事务列表
  • 读取数据时,通过 undo log 链找到对当前事务可见的版本
  • SELECT 不加锁(快照读),通过 Read View 实现一致性读

四、锁的分类

按粒度:表锁(开销小,并发低)、行锁(开销大,并发高,InnoDB 默认)

按类型

  • 共享锁(S锁):SELECT … LOCK IN SHARE MODE,允许多个事务同时读
  • 排他锁(X锁):SELECT … FOR UPDATE / INSERT / UPDATE / DELETE,独占
  • 意向锁(IS/IX):表级锁,表明事务意图加行锁,避免逐行检查冲突
  • 间隙锁(Gap Lock):锁定索引间的间隙,防止幻读
  • 临键锁(Next-Key Lock):行锁 + 间隙锁,InnoDB 的默认行锁形式

五、死锁分析与预防

死锁是两个事务互相等待对方释放锁。InnoDB 会自动检测并回滚代价较小的事务。

预防策略:

  1. 保持固定的加锁顺序(所有事务按相同顺序访问表/行)
  2. 减小事务粒度,尽快提交事务
  3. 使用 SELECT … FOR UPDATE 时确保有合适索引,避免全表锁
  4. 业务允许时降低隔离级别(RC 不使用间隙锁,死锁概率更低)

查看死锁信息:SHOW ENGINE INNODB STATUS\G

六、常用锁相关命令

-- 查看当前锁等待
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

-- 查看事务列表
SELECT * FROM information_schema.INNODB_TRX;

-- 查看锁信息(MySQL 8.0)
SELECT * FROM performance_schema.data_locks;

-- 手动提交/回滚
BEGIN; -- 或 START TRANSACTION
COMMIT;
ROLLBACK;

总结

理解 MVCC 是读写不冲突的关键,理解锁机制是解决死锁和性能问题的基础。实际开发中要尽量缩短事务时长,合理选择隔离级别,为 WHERE 条件字段加索引(避免锁升级为表锁),这三点能解决 80% 的锁相关问题。

发表评论