死锁与悲观锁乐观锁不是一类东西
Posted InDataBase
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死锁与悲观锁乐观锁不是一类东西相关的知识,希望对你有一定的参考价值。
一般而言,对数据操作会出现以下场景:
◎ 查询自己之前修改的数据
◎ 修改自己之前修改的数据
◎ 查询别人修改的数据(一致性读)
◎ 修改别人修改的数据行(存在锁问题)
◎ 修改别人修改不在同一行的数据块(不存在写一致性问题)
前两组,是单用户操作
后三组,是多用户并发操作
对于一致性读,如果有人修改但未提交,Oracle是通过读取回滚段来取得修改之前的数据,来保持数据一致性,避免错读。
对于并发操作,Oracle可以通过悲观锁和乐观锁来解决。
⊙ 悲观锁
悲观的认为我这段时间内,别人一定会操作数据
虽然别人也可能没人操作,但就是很悲观的认为有人。
所以悲观锁一上来就把我要操作的数据锁住,别人都操作不了。
悲观锁的方法是语句级的(如SQL语句中写上FOR UPDATE)SQL来实现的。
⊙ 乐观锁
乐观的认为我这段时间内 没有别人会操作数据
那我们怎么样处理在乐观的情况下,真有人操作数据呢?
一般有2种解决方案
1. 使用版本列的乐观锁定
如果我执行以下三步操作,当有人在tttttt时间段进行了数据操作,如果能捕获到,即可进行识别。
select
tttttt
update
这是一个简单的实现,如果你想保护数据库表不出现丢失更新问题,应对每个要保护的表增加一列。
这一列一般是NUMBER 或DATE/TIMESTAMP 列,通常通过表上的一个行触发器来维护。每次修改行时,这个触发器要负责递增NUMBER 列中的值,或者更新DATE/TIMESTAMP 列。
例如:
Create table t
(
Id number,
Name varhcar2(30),
Update_time timestamp default systimestamp not null
)
这里增加的列名是update_time
应用只需验证请求更新那一刻,数据库中这一列的值与最初读出的值是否匹配。
如果两个值相等,就说明这一行未被更新过。
2. 使用ORA_ROWSCN 的乐观锁定
可以获取某个块最后修改的SCN,甚至可以查到基于行最后一次修改的SCN。
通过比较SCN来发现是否有值被别人修改。
适合已经发布的程序,因为不需要增加太多的代码。
那么死锁是什么?
当两个用户分别占有彼此希望对方持有的资源时,而且自己获取的(别人想要的)资源不释放,就会发生死锁。
死锁产生后,Oracle会随机选择一方,对其进行回滚,以解除死锁。
这里要区分死锁与等待。
当A锁定id=1的记录时,B去锁定id=1的记录,此时B就需要等待,此时B不能进行其他SQL,直到A完成事务。
这种现象叫“等待”。
来个实验就明白了。
先创建测试用的表以及数据
开始执行
左侧Session取得了id=1,3的锁
右侧Session取得了id=2,4的锁
左侧Session 要取得id=2的锁,在等待
右侧Session 要取得id=1的锁,此时产生了死锁
Oracle随机选择到了左侧Session,将其进行了回滚。
此时在左侧Session中查询,发现其之前修改id=1,3的数据还在。说明Oracle处理死锁时的回滚是语句级的。
与其他数据库不同,DB2、SYBASE等都是事务级的回滚。
同时,右侧的Session要取得id=1的锁,依然在等待。
悲观锁、乐观锁是为了处理并发的一种解决方案。
处理死锁数据库为防止资源耗尽的一种处理机制。
等待是一个悲观Session的无奈。
翻翻历史,温故知新
以上是关于死锁与悲观锁乐观锁不是一类东西的主要内容,如果未能解决你的问题,请参考以下文章