最近访客

数据库锁机制:共享锁(S 锁)与排他锁(X 锁)的区别与应用

在并发数据库系统中,锁(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 锁)用于写操作(INSERTUPDATEDELETE),它会独占资源。

  • 独占性强:一旦某行被加上 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 (读,防止别人写) UPDATEDELETEINSERTSELECT ... 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,若文章内容或图片失效,请留言或联系站长反馈!
本站资源均仅供学习和研究使用,请在下载后24小时内删除!
© 版权声明
THE END
点赞16 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容