一、严格二相锁(S2PL)
二阶段锁(两相锁):事务在第一阶段依次获得锁,第二阶段保持锁,第三阶段依次释放锁
严格二相锁:事务在第一阶段依次获得锁,第二阶段保持锁,第三阶段同时释放所有锁。
注意两段协议是为了保证事务的可串行性,保证串行事务的正确性。
两相锁的图描述:
严格两相锁的图描述:
这样,严格两相锁是没有级联中止的。
二、 事务隔离级别以及现象
不同的事务的隔离级别会产生不同的错误现象,这一篇主要说三种错误:幻读Phantom,模糊读Fuzzy read,脏读Dirty read。
定义是:
脏读:读取x的未提交值。
模糊读:读到x的不同的已提交值。
幻读:读取一个新的已提交的插入行。
注意模糊读和幻读的区别,模糊读的数据总数没有变化,比如原来是20条数据,现在还是20条数据,但是读的值却不一样。幻读的数据总数发生了变化,原来20条数据,现在21条。
我们举一些例子:
1.模糊读(丢失更新)
s: r
1
[x], r
2
[x], r
1
[x], r
2
[x], w
1
[x], c
1
, w
2
[x], c
2
TA1: r
1
[x], r
1
[x], w
1
[x], c
1
TA2: r
2
[x], r
2
[x], w
2
[x] , c
2
TA1 |
TA2 |
读x,假设x=10 |
|
|
读x,x=10 |
读x,x=10 |
|
|
读x,x=10 |
写x,x值改变 x=x+1=11 |
|
提交 |
|
|
写x,x值改变,x= x+10=20,出错XXX |
|
提交 |
我们发现,TA1本来已经改变x的值并提交,此时x=11,再加10,本来等于21,但是TA2加完之后却等于20,这就是模糊读,这种错误丢失了更新,原因是,别的事物更新值之后,TA2并没有再次读取x,如果TA1提交后,TA2再读一下x,这种错误就能避免。
2.脏读
r
1
[x], r
2
[x], w
2
[x], r
1
[x], w
2
[y], c
1
TA1 |
TA2 |
读x |
|
|
读x |
|
写x |
读x,出现脏读风险, 因为TA2修改的 x值并未提交, 一旦TA2回滚, TA1读的这个x 就是脏读 |
|
|
写y |
提交 |
|
3.幻读:
TA1 执行: SELECT*FROM mytabl
获得一个结果1
TA2 : 插入一行r并提交.
TA1 再次执行 SELECT*FROM mytabl
获得不同的结果2=结果1+{r}
结果1和结果2出现不同的行数,出现幻觉
这就是幻读。
为了避免这三个问题,数据库事务管理设置了四个不同的安全级别来保证不同的情况下都能相对安全的运行数据库。