如何加共享锁?

MySQL 中如何加共享锁(S锁 Share Lock)


一、什么是共享锁(S锁)?

  • 共享锁(Share Lock,S锁) 是一种读锁,允许多个事务同时读取同一份数据,但在加锁期间禁止任何事务修改(UPDATE/DELETE)这份数据

  • 特点

    • 多个事务可以同时对同一数据加 S 锁,共享读取;

    • 但在加了 S 锁的数据上,不能加 X 锁(排他锁,修改、删除);

    • 遇到修改冲突时,会阻塞直到前面的 S 锁释放。


二、如何加共享锁?(标准写法)

✅ 通过 SELECT ... LOCK IN SHARE MODE

START TRANSACTION; -- 显式开启事务
SELECT * FROM 表名 WHERE 条件 LOCK IN SHARE MODE;
-- 后续可以基于查询结果进行其他操作
COMMIT; -- 提交事务

示例:

START TRANSACTION;
SELECT * FROM user WHERE id = 10 LOCK IN SHARE MODE;
COMMIT;

解析:

  • 查询 id=10user 表记录时,加上了共享锁

  • 其他事务可以继续读取 id=10 的记录,但在当前事务提交前,不能修改或删除这一行,否则会被阻塞。


三、应用场景

应用场景类型示例原因
1. 读后校验,不修改比如读取某用户订单状态,确保未被其他事务更改,防止并发异常。共享锁能保护读到的数据在校验完成前不会被修改。
2. 防止幻读(搭配显式加锁)有些自定义事务控制的业务,比如乐观检查库存数量。保证读取到的数据在提交前是可靠的。

四、注意事项

1. 必须在事务中使用

  • 如果你没有用 START TRANSACTION 显式开启事务,MySQL默认是自动提交模式,SELECT ... LOCK IN SHARE MODE 结束后锁立即释放,等于没意义。

所以正确姿势:

START TRANSACTION;
SELECT ... LOCK IN SHARE MODE;
-- 进行一些基于读取数据的逻辑判断
-- 或根据查询结果进一步处理
COMMIT;

2. 共享锁与排他锁互斥

  • 如果某行被加了共享锁,其他事务想对这行加排他锁(比如更新或删除),必须等待共享锁释放。

示例:

  • 事务A

    START TRANSACTION;
    SELECT * FROM user WHERE id=1 LOCK IN SHARE MODE;
    
  • 事务B

    START TRANSACTION;
    UPDATE user SET name='new' WHERE id=1; -- 被阻塞
    

3. 对主键/唯一索引字段加共享锁最有效

  • 加锁基于索引主键或唯一索引查询加锁范围小、效率高。

  • 如果查询列无索引,InnoDB可能锁全表扫描,极大降低并发性。

建议加锁操作要走索引!


五、共享锁和其他锁关系简表

锁类型允许并发读?允许并发写?典型用途
无锁(普通 SELECT)快速读取
共享锁(S锁)读取保护,防止别人改
排他锁(X锁)读写独占,比如 FOR UPDATE

最后一段总结

✅ 加共享锁的标准方式是 SELECT ... LOCK IN SHARE MODE,必须在事务中使用,允许多个事务同时读但禁止写,适合在高并发业务中需要保护读取数据一致性的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值