数据库里的“锁”事:共享锁、排他锁与三级封锁协议

数据库就像一个脾气古怪的图书馆管理员。当多个读者同时想借阅同一本书时,它会突然变得严肃:"不行!你得排队,否则书页会被撕烂!"

而这一切的背后,正是数据库的"封锁机制"在默默工作。今天,我们就来聊聊数据库中的"锁"事------共享锁、排他锁 ,以及它们的"三重保护伞"三级封锁协议


一、锁的基本概念:共享锁 vs 排他锁

1. 共享锁(Shared Lock,S锁):图书馆的"共读区"

  • 特点 :允许多个事务同时读取同一数据,但禁止任何事务修改数据。
  • 比喻:就像图书馆的"共读区",大家可以在同一张桌子上读书,但不能拿笔乱涂乱画。
  • 应用场景:适用于查询操作(SELECT),例如查看商品库存、用户余额等。

举个栗子🌰

假设事务A和事务B都想读取"用户余额"表,共享锁会让它们同时进入"共读区"。但如果事务C想修改余额,它必须等A、B都离开后,才能进入"修改区"。


2. 排他锁(Exclusive Lock,X锁):图书馆的"私人办公室"

  • 特点独占修改权,其他事务不能读也不能写。
  • 比喻:就像图书馆的"私人办公室",只有你能进去,别人只能在外面排队。
  • 应用场景:适用于写操作(INSERT/UPDATE/DELETE),例如修改订单状态、扣减库存等。

举个栗子🌰

事务A正在修改"库存表"中的某件商品数量,排他锁会阻止事务B同时修改同一商品。如果事务B想读取该商品,也必须等事务A释放锁。


二、三级封锁协议:数据库的"三重防护墙"

封锁协议就像数据库的"安全等级",从一级到三级,逐步升级保护强度。它们的核心目标是:防止并发操作导致的数据混乱(如脏读、不可重复读、幻读)。

一级封锁协议:基础防护,防止"丢失修改"

  • 规则 :事务修改数据前必须加排他锁,直到事务结束才释放。
  • 解决的问题丢失修改(两个事务同时修改同一数据,后者的修改会覆盖前者)。
  • 类比:就像两个人同时修改一份Excel表格,最后只保存了一个人的改动。

场景举例

银行转账场景中,事务A将用户A的余额从100元改为80元,事务B同时将余额从100元改为50元。如果没有排他锁,最终余额可能是80元或50元,导致数据错误。


二级封锁协议:升级防护,防止"脏读"

  • 规则 :在一级协议基础上,事务读取数据前加共享锁,读完即释放。
  • 解决的问题脏读(读取到其他事务未提交的临时数据)。
  • 类比:就像在餐厅点餐,服务员告诉你"这道菜还没上,但你可以先尝尝"------结果菜可能中途被撤下。

场景举例

事务A正在修改用户余额(从100元改为80元),但尚未提交。事务B读取余额时,如果共享锁未释放,事务B可能会读到"80元"的临时值。若事务A回滚(余额恢复为100元),事务B就陷入了"脏读"。


三级封锁协议:终极防护,防止"不可重复读"

  • 规则 :在一级协议基础上,事务读取数据前加共享锁,直到事务结束才释放。
  • 解决的问题不可重复读(同一事务内多次读取,结果不一致)。
  • 类比:就像你买了一件衣服,付完钱后发现价格突然变了------这就是"不可重复读"的翻车现场。

场景举例

事务A在统计某商品的总销量时,事务B中途修改了销量。如果共享锁未持续到事务A结束,事务A可能会看到两次不同的统计结果。


三、锁的"副作用"与应对策略

虽然锁能保护数据一致性,但也可能引发"副作用":

  1. 死锁 :多个事务相互等待对方释放锁,像"你让我走,我让你先"的尴尬场面。
    • 解决方案:超时检测、死锁检测算法(如"等待图法")。
  2. 性能瓶颈 :锁粒度越细(如行级锁),并发性能越高,但管理成本也越高。
    • 建议:根据业务场景选择锁粒度(行锁 vs 表锁)。

四、实际应用:MySQL中的锁机制

以MySQL的InnoDB引擎为例:

  • 共享锁SELECT ... LOCK IN SHARE MODE
  • 排他锁SELECT ... FOR UPDATE
  • 锁相容性:共享锁之间兼容,但与排他锁互斥。

举个栗子🌰

sql 复制代码
-- 事务A:加共享锁,其他事务可读但不能写
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;

-- 事务B:加排他锁,需等事务A释放共享锁
SELECT * FROM users WHERE id = 1 FOR UPDATE;

五、总结:锁的哲学

数据库的封锁机制就像一场"秩序与效率"的平衡术:

  • 共享锁:让读操作"和平共处"。
  • 排他锁:为写操作"保驾护航"。
  • 三级协议:从基础到终极,层层加固数据一致性。

最后送大家一句话

"锁住了数据库的小脾气,才能让数据在并发中优雅地跳舞。"

下次当你在代码中使用FOR UPDATELOCK IN SHARE MODE时,不妨想想这些锁背后的故事------它们不仅是代码的关键词,更是数据世界的"守门人"!

相关推荐
dylan_QAQ9 分钟前
【附录】为什么说 Spring 中 BeanFactory的是延迟加载 和轻量级的?有什么证据?
后端·spring
回家路上绕了弯36 分钟前
深度理解 volatile 与 synchronized:并发编程的两把钥匙
java·后端
程序员清风36 分钟前
ThreadLocal在什么情况下会导OOM?
java·后端·面试
就是帅我不改43 分钟前
基于领域事件驱动的微服务架构设计与实践
后端·面试·架构
JohnYan44 分钟前
Bun技术评估 - 25 Utils(实用工具)
javascript·后端·bun
我要成为Java糕手1 小时前
支付宝芝麻免押支付集成指南及技术对接验收(Java版)
javascript·后端
anthem371 小时前
3、Python持续集成与部署
后端
用户4099322502121 小时前
如何让你的FastAPI Celery Worker在压力下优雅起舞?
后端·github·trae
anthem371 小时前
5、Python文档生成与API设计
后端
ruokkk1 小时前
当你配置了feign.sentinel.enable=true时发生什么
后端·架构