在并发数据库系统中,锁(Lock)是保证数据一致性和隔离性的核心机制。MySQL(InnoDB 引擎)最常见的两种锁就是 共享锁(Shared Lock, S 锁) 和 排他锁(Exclusive Lock, X 锁)。很多开发者在写 SQL 时都遇到过“锁等待”、“死锁”等问题,本质上都与这两种锁息息相关。本文将带你全面了解 S 锁与 X 锁的区别和应用场景。
一、什么是共享锁(S 锁)?
共享锁(Shared Lock,简称 S 锁)允许多个事务同时读取同一行记录,但不允许修改。
-
并发性高:多个事务可以同时持有同一行的 S 锁。
-
限制:一旦某行被加上 S 锁,其他事务不能对其加 X 锁(即不能修改)。
使用场景
-- 给数据加共享锁,只能读,不能改
SELECT * FROM product_audit
WHERE id = 1
LOCK IN SHARE MODE;
常见于需要“读一致性”的场景,例如:
-
读数据时希望确保这条数据不会在读取期间被修改;
-
在业务逻辑中,需要保证“读后再写”的一致性。
二、什么是排他锁(X 锁)?
排他锁(Exclusive Lock,简称 X 锁)用于写操作(INSERT、UPDATE、DELETE),它会独占资源。
-
独占性强:一旦某行被加上 X 锁,其他事务既不能加 S 锁(不能读),也不能加 X 锁(不能写)。
-
保证一致性:持有 X 锁的事务可以安全地对数据进行修改。
使用场景
-- 给数据加排他锁,只有自己能读写,别人不能访问
SELECT * FROM product_audit
WHERE id = 1
FOR UPDATE;
常见于“读后立刻要修改”的场景,例如:
-
下单前锁定库存行,避免并发超卖;
-
修改记录时,确保不会出现其他事务并发修改。
三、S 锁与 X 锁的区别对比
| 特性 | 共享锁(S 锁) | 排他锁(X 锁) |
|---|---|---|
| 是否允许读 | ✅ 可以。多个事务可同时持有 S 锁。 ❌ 但若存在 X 锁,其他事务不能再读。 |
✅ 持有 X 锁的事务自己可以读。 ❌ 其他事务不能加 S 锁或 X 锁。 |
| 是否允许写 | ❌ 不允许写。持有 S 锁的事务只能读,不能修改。 | ✅ 持有 X 锁的事务可以写。 ❌ 其他事务不能写该行。 |
| 并发性 | 高(适合并发读)。 | 低(独占,适合修改场景)。 |
| 锁兼容性 | S 锁 兼容 S 锁; ❌ 与 X 锁不兼容。 |
X 锁 ❌ 不兼容 S 锁和 X 锁(完全独占)。 |
| 典型用法 | SELECT ... LOCK IN SHARE MODE (读,防止别人写) |
UPDATE、DELETE、INSERT、SELECT ... FOR UPDATE (写,独占) |
四、锁兼容矩阵
| 当前锁 \ 请求锁 | S 锁请求 | X 锁请求 |
|---|---|---|
| S 锁 | ✅ 允许 | ❌ 阻塞 |
| X 锁 | ❌ 阻塞 | ❌ 阻塞 |
简单理解:
-
S vs S:大家都能读,互不影响;
-
S vs X:谁先来谁占用,另一个要等待;
-
X vs X:只能有一个事务独占;
五、应用案例
案例 1:防止并发超卖
BEGIN;
SELECT stock FROM products
WHERE id = 1001
FOR UPDATE; -- 加 X 锁
-- 检查库存
-- 如果足够,减库存
UPDATE products
SET stock = stock - 1
WHERE id = 1001;
COMMIT;
这样可以确保多个用户同时下单时,只有一个事务能先减库存,避免超卖。
案例 2:并发读取不阻塞
-- 多个事务同时执行
SELECT * FROM orders
WHERE status = 'pending'
LOCK IN SHARE MODE;
这样多个事务可以同时读取“待处理订单”,但不能被修改,保证了读取的一致性。
六、总结
-
共享锁(S 锁):允许并发读,不允许写,适合需要一致性读取的场景。
-
排他锁(X 锁):独占数据,允许修改,适合需要安全写入的场景。
-
在高并发系统中,合理使用 S 锁和 X 锁,可以大幅减少死锁与性能问题。
🔑 一句话记忆:
-
S 锁:大家一起看,没人能改。
-
X 锁:我自己看,我自己改,别人别碰。
2025-09-11 17:52:56,若文章内容或图片失效,请留言或联系站长反馈!










暂无评论内容