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

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

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


一、锁的基本概念:共享锁 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时,不妨想想这些锁背后的故事------它们不仅是代码的关键词,更是数据世界的"守门人"!

相关推荐
努力的小郑11 分钟前
MySQL索引(三):字符串索引优化之前缀索引
后端·mysql·性能优化
IT_陈寒33 分钟前
🔥3分钟掌握JavaScript性能优化:从V8引擎原理到5个实战提速技巧
前端·人工智能·后端
程序员清风1 小时前
贝壳一面:年轻代回收频率太高,如何定位?
java·后端·面试
考虑考虑1 小时前
Java实现字节转bcd编码
java·后端·java ee
AAA修煤气灶刘哥2 小时前
ES 聚合爽到飞起!从分桶到 Java 实操,再也不用翻烂文档
后端·elasticsearch·面试
爱读源码的大都督2 小时前
Java已死?别慌,看我如何用Java手写一个Qwen Code Agent,拯救Java
java·人工智能·后端
星辰大海的精灵2 小时前
SpringBoot与Quartz整合,实现订单自动取消功能
java·后端·算法
天天摸鱼的java工程师3 小时前
RestTemplate 如何优化连接池?—— 八年 Java 开发的踩坑与优化指南
java·后端
一乐小哥3 小时前
一口气同步10年豆瓣记录———豆瓣书影音同步 Notion分享 🚀
后端·python
LSTM973 小时前
如何使用C#实现Excel和CSV互转:基于Spire.XLS for .NET的专业指南
后端