线上系统突然报出死锁异常,业务数据更新卡住,排查半天却连锁的类型都分不清?行锁、表锁、间隙锁到底有啥区别?S 锁和 X 锁的竞争又是如何引发死锁的?作为后端开发者,数据库锁机制是绕不开的核心知识点,更是保障系统数据一致性和并发性能的关键。本文将从基础锁类型到死锁排查,层层拆解 MySQL 锁机制,带你吃透每个核心要点。
一、核心锁类型基础:S 锁与 X 锁
数据库锁的核心目的是解决并发场景下的数据一致性问题。Shared Locks(共享锁,简称 S 锁)和 Exclusive Locks(排他锁,简称 X 锁)是所有锁机制的基础,几乎所有数据库都实现了这两种核心锁类型。
1.1 共享锁(S 锁):读锁不互斥
共享锁的核心特质是多个事务可以同时持有同一资源的 S 锁,互不干扰,但会阻塞 X 锁的获取。
- 适用场景:只读操作,比如
SELECT * FROM table WHERE id=1 LOCK IN SHARE MODE;(MySQL 中显式加 S 锁) - 核心规则:
- 事务 A 获取资源 R 的 S 锁后,其他事务可正常获取 R 的 S 锁(读 - 读兼容)
- 事务 A 获取资源 R 的 S 锁后,其他事务请求 R 的 X 锁会被阻塞,直至 A 释放 S 锁(读 - 写互斥)
1.2 排他锁(X 锁):写锁全互斥
排他锁的核心特质是同一资源同一时间只能被一个事务持有 X 锁,既阻塞其他 X 锁,也阻塞 S 锁。
- 适用场景:写操作(插入、更新、删除),MySQL 中默认对写操作加 X 锁,比如
UPDATE table SET name='test' WHERE id=1; - 核心规则:
- 事务 A 获取资源 R 的 X 锁后,其他事务请求 R 的 S 锁或 X 锁都会被阻塞(写 - 读、写 - 写均互斥)
- 事务 A 释放 X 锁后,阻塞的事务才会按优先级依次获取锁资源
排查锁问题时,先明确是读锁还是写锁的竞争,能快速缩小排查范围。
二、粒度区分:表锁与行锁
除了 S 锁和 X 锁的类型区分,按锁定资源的粒度,MySQL 锁可分为表锁(Table Lock)和行锁(Record Lock),两者的锁定范围和适用场景差异极大。
2.1 表锁:粗粒度锁,高效低并发
表锁是锁定整个数据表的锁机制,是 MySQL 中最基础、开销最小的锁类型。MyISAM 存储引擎默认支持表锁,InnoDB 也支持但不常用。
核心特性
- 锁定范围:整个数据表,无论操作涉及多少行数据
- 优缺点:
- ✅ 优点:加锁/解锁速度快,开销小,不会产生死锁
- ❌ 缺点:锁定粒度大,并发性能差,比如事务 A 更新表中 1 行数据,事务 B 更新同一表中另一行数据会被阻塞
加锁方式
-- 显式加表级 S 锁
LOCK TABLES table_name READ;
-- 显式加表级 X 锁
LOCK TABLES table_name WRITE;
-- 释放表锁
UNLOCK TABLES;
适用场景
- 读多写少的场景(如日志查询表)
- 批量操作场景(如批量导入数据,加表锁避免频繁行锁竞争)


