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 锁:都到事务结束 | 丢失更新、脏读、不可重复读 |
四、补充说明
-
两段锁协议(2PL) vs 三级封锁协议
- 三级封锁协议是针对特定异常设计的规则;
- 两段锁协议 (Growing Phase + Shrinking Phase)是保证可串行化调度的充分条件,与三级协议目的不同,但三级协议通常满足 2PL。
-
实际数据库实现
现代数据库(如 MySQL InnoDB)更多采用 MVCC + 多粒度锁 来实现高并发,而非单纯依赖封锁协议。但理解封锁协议仍是理论基础。
五、记忆口诀
一级防丢失,
二级加读锁(防脏读),
三级锁到底(防不可重复读)。