全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-15 8 分钟 ✍️ juanwangdev

锁机制概述

MySQL锁机制保证多事务并发访问数据的一致性,防止脏读、丢失更新等问题。

锁的分类

按锁粒度分类

类型范围说明
全局锁整个数据库全库只读,备份场景
表级锁整张表MyISAM默认,InnoDB支持
行级锁单行数据InnoDB默认,高并发友好
页级锁数据页BDB引擎使用

按锁类型分类

类型符号说明
共享锁S读锁,允许并发读
排他锁X写锁,独占访问
意向共享锁IS表级,表示有意获取行S锁
意向排他锁IX表级,表示有意获取行X锁

按锁模式分类

类型说明
Record Lock记录锁,锁单行
Gap Lock间隙锁,锁区间(不含记录)
Next-Key Lock记录+间隙锁

InnoDB锁类型

共享锁(S Lock)

SQL
-- 读锁,允许并发读,阻塞写
SELECT * FROM orders WHERE id = 1 LOCK IN SHARE MODE;
-- 或 MySQL 8.0+
SELECT * FROM orders WHERE id = 1 FOR SHARE;

-- 其他事务可读,不可写
-- 事务1:持有S锁
-- 事务2:可获取S锁(并发读)
-- 事务2:无法获取X锁(阻塞)

排他锁(X Lock)

SQL
-- 写锁,独占访问,阻塞其他读写
SELECT * FROM orders WHERE id = 1 FOR UPDATE;

-- DML自动获取X锁
UPDATE orders SET amount = 100 WHERE id = 1;
DELETE FROM orders WHERE id = 1;
INSERT INTO orders VALUES (...);

-- 其他事务无法获取任何锁
-- 事务1:持有X锁
-- 事务2:无法获取S锁/X锁(阻塞)

意向锁

SQL
意向锁是表级锁,表示事务有意在行上加锁:

IS(意向共享锁):事务将在某些行上加S锁
IX(意向排他锁):事务将在某些行上加X锁

作用:快速判断表是否有行锁冲突
无需逐行检查是否有锁

锁兼容性矩阵

当前锁SXISIX
S
X
IS
IX
SQL
说明:
✅ 兼容:可同时持有
❌ 冲突:需等待对方释放

表级锁

LOCK TABLES

SQL
-- 读锁(共享锁)
LOCK TABLE orders READ;
-- 可读,不可写,其他事务可读
UNLOCK TABLES;

-- 写锁(排他锁)
LOCK TABLE orders WRITE;
-- 可读写,其他事务阻塞
UNLOCK TABLES;

元数据锁(MDL)

SQL
-- DDL操作自动获取MDL锁
ALTER TABLE orders ADD COLUMN new_col INT;

-- MDL锁类型:
-- MDL_SHARED:读操作
-- MDL_EXCLUSIVE:DDL操作

-- DDL期间阻塞所有DML
-- 长事务会阻塞DDL

全局锁

使用场景

SQL
-- 全库只读,用于备份
FLUSH TABLES WITH READ LOCK;

-- 执行备份
-- mysqldump --single-transaction(推荐,不锁表)

-- 释放全局锁
UNLOCK TABLES;

行级锁实现

Record Lock

SQL
-- 锁定单行记录
UPDATE orders SET amount = 100 WHERE id = 1;
-- 对id=1的记录加X锁

-- 索引匹配才生效,否则退化为表锁
UPDATE orders SET amount = 100 WHERE user_id = 1;
-- 若user_id有索引:行锁
-- 若user_id无索引:表锁(扫描所有行)

Gap Lock

SQL
-- 锁定记录之间的间隙
-- 防止幻读(其他事务插入)

-- 示例:id有值1,5,10
SELECT * FROM orders WHERE id > 5 AND id < 10 FOR UPDATE;
-- 锁定间隙(5,10),防止插入id=6,7,8,9

Next-Key Lock

SQL
-- Record Lock + Gap Lock
-- 锁定记录及其前间隙

-- 示例:id有值1,5,10
SELECT * FROM orders WHERE id = 5 FOR UPDATE;
-- 锁定(1,5]区间
-- 防止插入id=2,3,4和修改id=5

锁的获取时机

操作锁类型
SELECT(普通)无锁(MVCC)
SELECT ... LOCK IN SHARE MODES锁
SELECT ... FOR UPDATEX锁
INSERTX锁
UPDATEX锁
DELETEX锁
text
普通SELECT使用MVCC快照读,不加锁
锁定读和DML操作会加锁

查看锁信息

查看当前锁

text
-- MySQL 8.0+
SELECT * FROM performance_schema.data_locks;

-- 锁等待关系
SELECT * FROM performance_schema.data_lock_waits;

-- MySQL 5.7
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

-- 当前事务
SELECT * FROM information_schema.INNODB_TRX;

查看锁等待

text
SELECT
    r.trx_id AS waiting_trx,
    r.trx_mysql_thread_id AS waiting_thread,
    b.trx_id AS blocking_trx,
    b.trx_mysql_thread_id AS blocking_thread,
    r.trx_query AS waiting_query
FROM information_schema.INNODB_LOCK_WAITS w
JOIN information_schema.INNODB_TRX r ON w.requesting_trx_id = r.trx_id
JOIN information_schema.INNODB_TRX b ON w.blocking_trx_id = b.trx_id;

要点总结

  • MySQL锁分为全局锁、表锁、行锁三种粒度
  • InnoDB默认行级锁,支持高并发
  • 共享锁(S)允许并发读,排他锁(X)独占访问
  • 意向锁(IS/IX)是表级锁,快速判断行锁冲突
  • 行锁包括Record Lock、Gap Lock、Next-Key Lock
  • 普通SELECT不加锁(MVCC),DML和锁定读加锁
  • 通过performance_schema查看锁信息

📝 发现内容有误?点击此处直接编辑

← 上一篇 行锁与表锁
下一篇 → 锁等待与超时
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库