第11章并发控制
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
32
冲突可串行化调度
【例4】调度Sc1= R1(A) W1(A) R2(A) W2(A) R1(B) W1(B) R2(B) W2(B) (1)交换 W2(A) 与R1(B) W1(B) 得到:
R1(A) W1(A) R2(A) R1(B) W1(B) W2(A) R2(B) W2(B) (2)交换 R2(A) 与R1(B) W1(B) 得到:
25
死锁问题 ①超时法
即一个事务在等待的时间超过了规定的时限后就 认为发生了死锁。
这种方法非常不可靠,如果设置的等待时限长, 则不能及时发现死锁;如果设置的等待时限短,则 可能会将没有发生死锁的事务误判为死锁。
26
死锁问题
②等待图法
即通过有向图判定事务是否是可 串行化的,如果是则说明没有发生 死锁,否则说明发生了死锁。
后两种不可重复读有时也称为幻 影现象(phantom row)。
T1
T2
读A=1,B=2 求A+B=3
读B=2
B=B*2 写回B=4
读A=1,B=4 求A+B=5
(验算不对)
6
3. 读脏数据
(1)事务T1修改某一数据, 并将其写回磁盘;
(2)事务T2读取同一数据后;
(3)事务T1由于某种原因被 撤 消 , 这 时 事 务 T1 已 修 改 过 的数据恢复原值;
15
2. 二级封锁协议
【定义】一级封锁协议+事务T在读取数据R前必须 先加S锁,读完后即可释放S锁 二级封锁协议可以防止丢失修改和读“脏”数据。 在二级封锁协议中,由于读完数据后即可释放S锁, 所以它不能保证可重复读。
16
二级封锁协议
T1
① Xlock C 读C= 100 C←C*2 写回C=200
②
③ 读A=50 读B=100 求和=150 Commit Unlock A Unlock B
④
⑤
T2
Xlock B 等待 等待 等待 等待 等待 等待 等待 等待 获得Xlock B 读B=100 B←B*2 写回B=200 Commit Unlock B
可重复读
三级封锁协议: 丢失修改? 可以防止 可重复读? 能保证 读脏数据? 可以防止
T1
T2
Slock B Y=B=2 Unlock B Xlock A A=Y+1
写回A(=3)
Unlock A
Slock A X=A=3 Unlock A Xlock B B=X+1
写回B(=4)
Unlock B
T1
T2
Slock A X=A=2 Unlock A Xlock B B=X+1
写回B(=3)
读 A=16
A=A-1
出售1
事务T2
A=A-1=15;
(4)乙售票点 这种数据库的不一致是由并发操作引起的。
卖出一张机票, 并发操作引起的数据不一致性包括三类:丢
A=A-1=15;
失修改、不可重复读和读脏数据。
4
1. 丢失修改
(1)丢失修改是指事 务T1与事务T2从数 据库中读入同一数据 并修改。
(1)排它锁(eXclusive lock):写锁
若事务T对数据对象A加上X锁,则只允许T读取 和修改A,其它任何事务都不能再对A加任何类型的 锁,直到T释放A上的锁。
(2)共享锁(Share lock):读锁
若事务T对数据对象A加上S锁,则事务T可以读 A但不能修改A,其它事务只能再对A加S锁,而不 能加X锁,直到T释放A上的S锁。
Sc2= R1(A) W1(A) R1(B) W1(B) R2(A) W2(A) R2(B) W2(B)
Sc2等价于一个串行调度T1,T2。所以,调度 Sc1是冲突可串行化调度。
33
冲突可串行化调度
【例5】有3个事务T1= W1(Y) W1(X), T2= W2(Y) W2(X), T3= W3(X) 调度L1= W1(Y) W1(X) W2(Y) W2(X) W3(X) 调度L2= W1(Y) W2(Y) W2(X) W1(X) W3(X) L1是一个串行调度 L2不满足冲突可串行化。但是L2是可串行化的,因 为L2执行的结果与调度L1是相同的。
③A←A-1 写回A=15 Commit Unlock A
④
⑤
T2
Xlock A 等待 等待 等待 等待 获得Xlock A 读A=15 A←A-1 写回A=14 Commit Unlock A
没有丢失修改
13
一级封锁协议
T1
① Xlock A 获得
② 读A=16 A←A-1 写回A=15
③…
④ Rollback Unlock A
28
例如, 现有有两个事务, 分别包含下列操作: (1)事务T1: 读B; A=B+1; 写回A; (2)事务T2: 读A; B=A+1; 写回B; (3)假设A, B的初值均为2。
按T1 → T2的次序执行结果为: A=3, B=4
按T2 → T1的次序执行结果为: B=3, A=4
29
两个事务的四种不同的调度策略
Unlock B
Slock B Y=B=3 Unlock B Xlock A A=Y+1
写回A(=4)
Unlock A
(a) 串行调度
(b) 串行调度
30
两个事务的四种不同的调度策略
T1
T2
Slock B Y=B=2
Slock A X=A=2 Unlock B Unlock A Xlock A A=Y+1
(1)丢失 修改? 可以 防止
(2)可重 复读? 不能 保证
(3)读脏 数据? 可以 防止
18
3. 三级封锁协议
【定义】一级封锁协议 + 事务T在读取数据R之前 必须先对其加S锁,直到事务结束才释放。
三级封锁协议可防止丢失修改、读脏数据和不 可重复读。
19
三级封锁协议
T1
① Xlock C 读C= 100 C←C*2 写回C=200
T2
读A=15
读“脏”数据
14
一级封锁协议
T1
①读A=50 读B=100 求和=150
②
③读A=50 读B=200 求和=250 (验算不对)
T2
Xlock B 获得 读B=100 B←B*2 写回B=200 Commit Unlock B
不可重复读 一级封锁协议: 丢失修改? 可以防止 可重复读? 不能保证 读脏数据? 不能防止
制法、多版本并发控制等。
8
11.2 封锁
1. 概念 封锁就是事务T在对某个数据对象(例如表、记
录等)操作之前,先向系统发出请求,对其加锁。 加锁后事务T就对该数据对象有了一定的控制,
在事务T释放它的锁之前,其它的事务不能更新此 数据对象。
封锁是实现并发控制的一个非常重要的技术。
9
2. 锁的类型
DBMS通常提供了多种类型的封锁。一个事务对 某个数据对象加锁后究竟拥有什么样的控制是由封 锁的类型决定的。
具体思路是:用节点来表示正在 运行的事务,用有向边来表示事务 之间的等待关系,如右图所示,如 果有向图中发现回路,则说明发生 了死锁。
27
11.5 并发调度的可串行性
11.5.1 可串行化调度 以不同的顺序串行执行事务也有可能会产生不同的 结果,但由于不会将数据库置于不一致状态,所以 都可以认为是正确的。 定义:几个事务的并行执行是正确的,当且仅当其 结果与按某一次序串行地执行它们时的结果相同。 这种并行调度策略称为可串行化(Serializable)的 调度。
10
11.3 封锁协议
在运用X锁和S锁对数据对象加锁时,需要约定 一些规则:封锁协议(Locking Protocol)。 包括: (1)何时申请X锁或S锁; (2)持锁时间、何时释放。
不同的封锁协议,在不同的程度上为并发操作的 正确调度提供一定的保证。 常用的封锁协议:三级封锁协议。
11
1. 一级 封锁协议
(4)事务T2读到的数据就与 数据库中的数据不一致,是 不正确的数据,又称为“脏” 数据。
T1
读C=1 C=C*2 写回C=2
T2 读C=2
ROLLBACK
C恢复为1
7
结论:
(1)产生上述三类不一致性的主要原因: 并发操作破坏了事务的隔离性,事务间相互干扰。 (2)并发控制的主要技术:封锁、时间戳、乐观控
②
③ ROLLBACK
(C恢复为100) Unlock C ④
⑤
T2
Slock C 等待 等待 等待 等待 获得Slock C 读C=100 Commit C Unlock C
不读“脏”数据
17
二级封锁协议
T1
① Sclock A 获得 读A=30
Unlock A ② Sclock B
获得 读B=100
第11章 并发控制
1
教学目标
1.了解事务的并发执行 2.理解死锁以及死锁的预防和判断方法 3.掌握封锁与隔离级别 4.掌握数据库并发控制封锁技术的原理
2
数据库是一个共享资源,可以供多个用户使 用。为了充分利用系统资源,允许多个事务并 行地执行。
T1 T2
T3
T1
T1
T2
T1
T2
T3
T2
T1
T3
T2
24
11.4.2 死锁
如果事务T1和T2各自封锁了数据R1和R2后,又各
自请求封锁R2和R1,因都无法获得而等待对方释
放的现象。
T1
T2
解决的两类方法:
封锁仓库关系
(1)预防死锁
封锁职工关系
一次封锁法
请求封锁职工关系 等待
顺序封锁法
(2)死锁的诊断与解除
超时法
请求封锁仓库关系 等待
等待图法
等待
等待
T3
(a)事务的串行执行方式
(b)事务的并行执行方式
图11.1 事务的执行方式
3
11.1 并发控制概述
例子
(1)甲售票点读 出某航班的机票 余额A=16;
(2)乙售票点读 出同一航班的机 票余额A=16;
(3)甲售票点卖 出一张机票,
售票点 A=16 出售1
读 A=A-1
事务T1
机票数量A
售票点
A=16 A=15 A=15
【定义】事务T在修改数据R之前必须先对其加X锁, 直到事务结束才释放。 正常结束(COMMIT) 非正常结束(ROLLBACK) 一级封锁协议可防止丢失修改。 在一级封锁协议中,如果是读数据,不需要加锁 的,所以它不能保证可重复读和不读“脏”数据。
12
一级封锁协议
T1
① Xlock A 获得
② 读A=16
21
封锁协议小结
22
11.4 活锁和死锁
11.4.1 活锁 如果事务T1封锁某数据后,事务T2请求封锁未
获得并等待,而T1释放锁后,事务T3请求封锁并 获得,T3释放锁后,事务T4请求封锁并获 得……T2可能永远等待。
23
解决办法: 采用先来先服务的策略。
当多个事务请求封锁同一数据对象时: (1)按请求封锁的先后次序对这些事务排队 (2)该数据对象上的锁一旦释放,首先批准申请 队列中第一个事务获得锁。
写回A(=3)
Xlock B B=X+1 Unlock A 写回B(=3)
UnlockБайду номын сангаасB
T1
T2
Slock B
Y=B=2
Unlock B
Xlock A
Slock A A=Y+1 等待 写回A(=3) 等待 Unlock A 等待
X=A=3
Unlock A Xlock B B=X+1
写回B(=4)
Unlock B
(a)不可串行调度
(b) 串行化的调度
31
11.5.2 冲突可串行化调度
(1)冲突操作的概念 冲突操作是指不同事务对同一个数据的读写操作
和写写操作: Ri(x)与Wj(x) //事务Ti读x,事务Tj写x Wi(x)与Wj(x) //事务Ti写x,事务Tj写x (2)冲突可串行化调度 一个调度Sc在保证冲突操作的次序不变的情况下, 通过交换两个事务的不冲突操作的次序得到另一个 调度Sc’,如果Sc’是串行的,称调度Sc为冲突可串 行化调度。
②
③ ROLLBACK
(C恢复为100) Unlock C ④
⑤
T2
Slock C 等待 等待 等待 等待 获得Slock C 读C=100 Commit C Unlock C
不读“脏”数据 三级封锁协议: 丢失修改? 可以防止 可重复读? 能保证 读脏数据? 可以防止
20
三级封锁协议
T1
① Slock A 读A=50 Slock B 读B=100 求和=150
Unlock B ③ 求和=130
T2
Xlock B
等待 等待
获得Xlock B 读B=100 B←B*2 写回B=200 Commit Unlock B
T1 (续)
T2
④Sclock A
获得
读A=30
Unlock A
Sclock B 获得
读B=200
Unlock B 求和=230 (验算不对)
二级封锁协 议:
(2)事务T2的提交结 果破坏了事务T1提 交的结果,导致事务 T1的修改被丢失。
T1
T2
读A=16
读A=16
A=A-1 写回A=15
A=A-1 写回A=15
5
2. 不可重复读
事务T1读取某一数据后: (1) 事务T2对其做了修改,当 事务T1再次读该数据时,得到与 前一次不同的值。
(2) 事务T2删除了其中部分记 录,当事务T1再次读取数据时, 发现某些记录神密地消失了。 (3) 事务T2插入了一些记录, 当事务T1再次按相同条件读取数 据时,发现多了一些记录。
冲突可串行化调度
【例4】调度Sc1= R1(A) W1(A) R2(A) W2(A) R1(B) W1(B) R2(B) W2(B) (1)交换 W2(A) 与R1(B) W1(B) 得到:
R1(A) W1(A) R2(A) R1(B) W1(B) W2(A) R2(B) W2(B) (2)交换 R2(A) 与R1(B) W1(B) 得到:
25
死锁问题 ①超时法
即一个事务在等待的时间超过了规定的时限后就 认为发生了死锁。
这种方法非常不可靠,如果设置的等待时限长, 则不能及时发现死锁;如果设置的等待时限短,则 可能会将没有发生死锁的事务误判为死锁。
26
死锁问题
②等待图法
即通过有向图判定事务是否是可 串行化的,如果是则说明没有发生 死锁,否则说明发生了死锁。
后两种不可重复读有时也称为幻 影现象(phantom row)。
T1
T2
读A=1,B=2 求A+B=3
读B=2
B=B*2 写回B=4
读A=1,B=4 求A+B=5
(验算不对)
6
3. 读脏数据
(1)事务T1修改某一数据, 并将其写回磁盘;
(2)事务T2读取同一数据后;
(3)事务T1由于某种原因被 撤 消 , 这 时 事 务 T1 已 修 改 过 的数据恢复原值;
15
2. 二级封锁协议
【定义】一级封锁协议+事务T在读取数据R前必须 先加S锁,读完后即可释放S锁 二级封锁协议可以防止丢失修改和读“脏”数据。 在二级封锁协议中,由于读完数据后即可释放S锁, 所以它不能保证可重复读。
16
二级封锁协议
T1
① Xlock C 读C= 100 C←C*2 写回C=200
②
③ 读A=50 读B=100 求和=150 Commit Unlock A Unlock B
④
⑤
T2
Xlock B 等待 等待 等待 等待 等待 等待 等待 等待 获得Xlock B 读B=100 B←B*2 写回B=200 Commit Unlock B
可重复读
三级封锁协议: 丢失修改? 可以防止 可重复读? 能保证 读脏数据? 可以防止
T1
T2
Slock B Y=B=2 Unlock B Xlock A A=Y+1
写回A(=3)
Unlock A
Slock A X=A=3 Unlock A Xlock B B=X+1
写回B(=4)
Unlock B
T1
T2
Slock A X=A=2 Unlock A Xlock B B=X+1
写回B(=3)
读 A=16
A=A-1
出售1
事务T2
A=A-1=15;
(4)乙售票点 这种数据库的不一致是由并发操作引起的。
卖出一张机票, 并发操作引起的数据不一致性包括三类:丢
A=A-1=15;
失修改、不可重复读和读脏数据。
4
1. 丢失修改
(1)丢失修改是指事 务T1与事务T2从数 据库中读入同一数据 并修改。
(1)排它锁(eXclusive lock):写锁
若事务T对数据对象A加上X锁,则只允许T读取 和修改A,其它任何事务都不能再对A加任何类型的 锁,直到T释放A上的锁。
(2)共享锁(Share lock):读锁
若事务T对数据对象A加上S锁,则事务T可以读 A但不能修改A,其它事务只能再对A加S锁,而不 能加X锁,直到T释放A上的S锁。
Sc2= R1(A) W1(A) R1(B) W1(B) R2(A) W2(A) R2(B) W2(B)
Sc2等价于一个串行调度T1,T2。所以,调度 Sc1是冲突可串行化调度。
33
冲突可串行化调度
【例5】有3个事务T1= W1(Y) W1(X), T2= W2(Y) W2(X), T3= W3(X) 调度L1= W1(Y) W1(X) W2(Y) W2(X) W3(X) 调度L2= W1(Y) W2(Y) W2(X) W1(X) W3(X) L1是一个串行调度 L2不满足冲突可串行化。但是L2是可串行化的,因 为L2执行的结果与调度L1是相同的。
③A←A-1 写回A=15 Commit Unlock A
④
⑤
T2
Xlock A 等待 等待 等待 等待 获得Xlock A 读A=15 A←A-1 写回A=14 Commit Unlock A
没有丢失修改
13
一级封锁协议
T1
① Xlock A 获得
② 读A=16 A←A-1 写回A=15
③…
④ Rollback Unlock A
28
例如, 现有有两个事务, 分别包含下列操作: (1)事务T1: 读B; A=B+1; 写回A; (2)事务T2: 读A; B=A+1; 写回B; (3)假设A, B的初值均为2。
按T1 → T2的次序执行结果为: A=3, B=4
按T2 → T1的次序执行结果为: B=3, A=4
29
两个事务的四种不同的调度策略
Unlock B
Slock B Y=B=3 Unlock B Xlock A A=Y+1
写回A(=4)
Unlock A
(a) 串行调度
(b) 串行调度
30
两个事务的四种不同的调度策略
T1
T2
Slock B Y=B=2
Slock A X=A=2 Unlock B Unlock A Xlock A A=Y+1
(1)丢失 修改? 可以 防止
(2)可重 复读? 不能 保证
(3)读脏 数据? 可以 防止
18
3. 三级封锁协议
【定义】一级封锁协议 + 事务T在读取数据R之前 必须先对其加S锁,直到事务结束才释放。
三级封锁协议可防止丢失修改、读脏数据和不 可重复读。
19
三级封锁协议
T1
① Xlock C 读C= 100 C←C*2 写回C=200
T2
读A=15
读“脏”数据
14
一级封锁协议
T1
①读A=50 读B=100 求和=150
②
③读A=50 读B=200 求和=250 (验算不对)
T2
Xlock B 获得 读B=100 B←B*2 写回B=200 Commit Unlock B
不可重复读 一级封锁协议: 丢失修改? 可以防止 可重复读? 不能保证 读脏数据? 不能防止
制法、多版本并发控制等。
8
11.2 封锁
1. 概念 封锁就是事务T在对某个数据对象(例如表、记
录等)操作之前,先向系统发出请求,对其加锁。 加锁后事务T就对该数据对象有了一定的控制,
在事务T释放它的锁之前,其它的事务不能更新此 数据对象。
封锁是实现并发控制的一个非常重要的技术。
9
2. 锁的类型
DBMS通常提供了多种类型的封锁。一个事务对 某个数据对象加锁后究竟拥有什么样的控制是由封 锁的类型决定的。
具体思路是:用节点来表示正在 运行的事务,用有向边来表示事务 之间的等待关系,如右图所示,如 果有向图中发现回路,则说明发生 了死锁。
27
11.5 并发调度的可串行性
11.5.1 可串行化调度 以不同的顺序串行执行事务也有可能会产生不同的 结果,但由于不会将数据库置于不一致状态,所以 都可以认为是正确的。 定义:几个事务的并行执行是正确的,当且仅当其 结果与按某一次序串行地执行它们时的结果相同。 这种并行调度策略称为可串行化(Serializable)的 调度。
10
11.3 封锁协议
在运用X锁和S锁对数据对象加锁时,需要约定 一些规则:封锁协议(Locking Protocol)。 包括: (1)何时申请X锁或S锁; (2)持锁时间、何时释放。
不同的封锁协议,在不同的程度上为并发操作的 正确调度提供一定的保证。 常用的封锁协议:三级封锁协议。
11
1. 一级 封锁协议
(4)事务T2读到的数据就与 数据库中的数据不一致,是 不正确的数据,又称为“脏” 数据。
T1
读C=1 C=C*2 写回C=2
T2 读C=2
ROLLBACK
C恢复为1
7
结论:
(1)产生上述三类不一致性的主要原因: 并发操作破坏了事务的隔离性,事务间相互干扰。 (2)并发控制的主要技术:封锁、时间戳、乐观控
②
③ ROLLBACK
(C恢复为100) Unlock C ④
⑤
T2
Slock C 等待 等待 等待 等待 获得Slock C 读C=100 Commit C Unlock C
不读“脏”数据
17
二级封锁协议
T1
① Sclock A 获得 读A=30
Unlock A ② Sclock B
获得 读B=100
第11章 并发控制
1
教学目标
1.了解事务的并发执行 2.理解死锁以及死锁的预防和判断方法 3.掌握封锁与隔离级别 4.掌握数据库并发控制封锁技术的原理
2
数据库是一个共享资源,可以供多个用户使 用。为了充分利用系统资源,允许多个事务并 行地执行。
T1 T2
T3
T1
T1
T2
T1
T2
T3
T2
T1
T3
T2
24
11.4.2 死锁
如果事务T1和T2各自封锁了数据R1和R2后,又各
自请求封锁R2和R1,因都无法获得而等待对方释
放的现象。
T1
T2
解决的两类方法:
封锁仓库关系
(1)预防死锁
封锁职工关系
一次封锁法
请求封锁职工关系 等待
顺序封锁法
(2)死锁的诊断与解除
超时法
请求封锁仓库关系 等待
等待图法
等待
等待
T3
(a)事务的串行执行方式
(b)事务的并行执行方式
图11.1 事务的执行方式
3
11.1 并发控制概述
例子
(1)甲售票点读 出某航班的机票 余额A=16;
(2)乙售票点读 出同一航班的机 票余额A=16;
(3)甲售票点卖 出一张机票,
售票点 A=16 出售1
读 A=A-1
事务T1
机票数量A
售票点
A=16 A=15 A=15
【定义】事务T在修改数据R之前必须先对其加X锁, 直到事务结束才释放。 正常结束(COMMIT) 非正常结束(ROLLBACK) 一级封锁协议可防止丢失修改。 在一级封锁协议中,如果是读数据,不需要加锁 的,所以它不能保证可重复读和不读“脏”数据。
12
一级封锁协议
T1
① Xlock A 获得
② 读A=16
21
封锁协议小结
22
11.4 活锁和死锁
11.4.1 活锁 如果事务T1封锁某数据后,事务T2请求封锁未
获得并等待,而T1释放锁后,事务T3请求封锁并 获得,T3释放锁后,事务T4请求封锁并获 得……T2可能永远等待。
23
解决办法: 采用先来先服务的策略。
当多个事务请求封锁同一数据对象时: (1)按请求封锁的先后次序对这些事务排队 (2)该数据对象上的锁一旦释放,首先批准申请 队列中第一个事务获得锁。
写回A(=3)
Xlock B B=X+1 Unlock A 写回B(=3)
UnlockБайду номын сангаасB
T1
T2
Slock B
Y=B=2
Unlock B
Xlock A
Slock A A=Y+1 等待 写回A(=3) 等待 Unlock A 等待
X=A=3
Unlock A Xlock B B=X+1
写回B(=4)
Unlock B
(a)不可串行调度
(b) 串行化的调度
31
11.5.2 冲突可串行化调度
(1)冲突操作的概念 冲突操作是指不同事务对同一个数据的读写操作
和写写操作: Ri(x)与Wj(x) //事务Ti读x,事务Tj写x Wi(x)与Wj(x) //事务Ti写x,事务Tj写x (2)冲突可串行化调度 一个调度Sc在保证冲突操作的次序不变的情况下, 通过交换两个事务的不冲突操作的次序得到另一个 调度Sc’,如果Sc’是串行的,称调度Sc为冲突可串 行化调度。
②
③ ROLLBACK
(C恢复为100) Unlock C ④
⑤
T2
Slock C 等待 等待 等待 等待 获得Slock C 读C=100 Commit C Unlock C
不读“脏”数据 三级封锁协议: 丢失修改? 可以防止 可重复读? 能保证 读脏数据? 可以防止
20
三级封锁协议
T1
① Slock A 读A=50 Slock B 读B=100 求和=150
Unlock B ③ 求和=130
T2
Xlock B
等待 等待
获得Xlock B 读B=100 B←B*2 写回B=200 Commit Unlock B
T1 (续)
T2
④Sclock A
获得
读A=30
Unlock A
Sclock B 获得
读B=200
Unlock B 求和=230 (验算不对)
二级封锁协 议:
(2)事务T2的提交结 果破坏了事务T1提 交的结果,导致事务 T1的修改被丢失。
T1
T2
读A=16
读A=16
A=A-1 写回A=15
A=A-1 写回A=15
5
2. 不可重复读
事务T1读取某一数据后: (1) 事务T2对其做了修改,当 事务T1再次读该数据时,得到与 前一次不同的值。
(2) 事务T2删除了其中部分记 录,当事务T1再次读取数据时, 发现某些记录神密地消失了。 (3) 事务T2插入了一些记录, 当事务T1再次按相同条件读取数 据时,发现多了一些记录。