数据库之并发控制

1.事务

事务:由一系列操作组成,这些操作,要么全做,要么全不做,拥有四种特

性,详解如下:

  • (操作) 原子性:要么全做,要么全不做
  • (数据)一致性:事务发生后数据是一致的,例如银行转账,不会存在A账户转
    出,但是B账户没收到的情况。
  • (执行)隔离性:任一事务的更新操作直到其成功提交的整个过程对其他事务
    都是不可见的,不同事务之间是隔离的,互不干涉。
  • (改变)持久性:事务操作的结果是持续性的。

事务是并发控制的前提条件,并发控制就是控制不同的事务并发执行,提高

系统效率,但是并发控制中存在下面三个问题:

  • 丢失更新:事务1对数据A进行了修改并写回,事务2也对A进行了修改并写回

    此时事务2写回的数据会覆盖事务1写回的数据,就丢失了事务1对A的更新。即

    对数据A的更新会被覆盖。

  • 不可重复读:事务2读A,而后事务1对数据A进行了修改并写回,此时若事务2

    再读A,发现数据不对。即一个事务重复读A两次,会发现数据A有误。

  • 读脏数据:事务1对数据A进行了修改后,事务2读数据A,而后事务1回滚,数

    据A恢复了原来的值,那么事务2对数据A做的事是无效的,读到了脏数据。

2.封锁协议

你对 X锁(排他锁)S锁(共享锁) 以及三级封锁协议 的理解基本正确,但为了更准确、系统地掌握并发控制中的封锁机制,下面我将为你全面梳理并补充细节,包括三级封锁协议的具体内容、各自能解决的问题,以及它们之间的区别。


一、锁的基本类型

锁类型 名称 允许操作 其他事务能否加锁?
S锁 共享锁(Shared Lock / Read Lock) 只读 可以加 S锁不能加 X锁
X锁 排他锁(Exclusive Lock / Write Lock) 读 + 写 不能加任何锁(S 或 X)

✅ 你的描述正确:

  • X锁:独占,其他事务完全不能访问(读/写都不行);
  • S锁:允许多个事务同时读,但禁止写。

二、三级封锁协议(Three-Level Locking Protocols)

这三级协议通过规定何时加锁、何时释放锁,来防止并发异常。级别越高,一致性越强,但并发性越低。


一级封锁协议
  • 规则
    事务在修改数据 R 之前 ,必须先对其加 X锁 ,并且直到事务结束(COMMIT 或 ROLLBACK)才释放
  • 可解决的问题 :✅ 丢失更新(Lost Update)
  • 不能解决的问题:❌ 脏读、❌ 不可重复读
  • 说明
    因为写操作被 X 锁保护到事务结束,所以两个事务不能同时写同一数据,避免了覆盖。

📌 注意:一级协议不要求对"读操作"加锁,所以仍可能读到未提交的数据(脏读)。


二级封锁协议
  • 规则
    • 在一级的基础上,事务在读取数据 R 之前 ,必须先加 S锁
    • S锁在读完后即可释放(不需要等到事务结束)。
  • 可解决的问题 :✅ 丢失更新 + ✅ 脏读(Dirty Read)
  • 不能解决的问题:❌ 不可重复读
  • 说明
    因为读的时候加了 S 锁,阻止了其他事务在此期间对 R 加 X 锁并修改(若对方要写,需等你读完),所以不会读到"正在被修改但未提交"的数据 → 避免脏读。
    但 S 锁很快释放,后续其他事务仍可修改 R,导致本事务再次读时值变了 → 仍存在不可重复读。

三级封锁协议
  • 规则
    • 在二级的基础上,S锁必须保持到事务结束才释放(不只是读完就放)。
  • 可解决的问题 :✅ 丢失更新 + ✅ 脏读 + ✅ 不可重复读
  • 不能解决的问题 :❌ 幻读(Phantom Read)(严格来说,封锁协议主要针对已存在的元组,幻读涉及新插入的行)
  • 说明
    由于 S 锁一直持有到事务结束,其他事务在整个过程中都无法修改该数据 → 同一事务内多次读取结果一致。

🔔 注意 :三级封锁协议并未直接解决幻读 。要完全避免幻读,通常需要范围锁(Range Lock) 或采用 Serializable 隔离级别(如使用谓词锁或串行执行)。


三、总结对比表

封锁协议 读操作加锁? 写操作加锁? 锁释放时机 解决的问题
一级 ❌ 不要求 ✅ 必须加 X 锁 X 锁:事务结束 丢失更新
二级 ✅ 加 S 锁 ✅ 加 X 锁 S 锁:读完即放X 锁:事务结束 丢失更新、脏读
三级 ✅ 加 S 锁 ✅ 加 X 锁 S 锁 & X 锁:都到事务结束 丢失更新、脏读、不可重复读

四、补充说明

  1. 两段锁协议(2PL) vs 三级封锁协议

    • 三级封锁协议是针对特定异常设计的规则
    • 两段锁协议 (Growing Phase + Shrinking Phase)是保证可串行化调度的充分条件,与三级协议目的不同,但三级协议通常满足 2PL。
  2. 实际数据库实现

    现代数据库(如 MySQL InnoDB)更多采用 MVCC + 多粒度锁 来实现高并发,而非单纯依赖封锁协议。但理解封锁协议仍是理论基础。


五、记忆口诀

一级防丢失,

二级加读锁(防脏读),

三级锁到底(防不可重复读)。


相关推荐
jiayou641 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤2 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区3 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1773 天前
《从零搭建NestJS项目》
数据库·typescript
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏4 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再4 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest4 天前
数据库SQL学习
数据库·sql
jnrjian4 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle