数据库总是死锁,不知道为什么!

melnnyy 发布于 2012/07/17 22:36
阅读 2K+
收藏 1

我们有一个java系统,和一个php系统

java用的是ssh框架,数据库是oracle的

两个系统经常会同时访问一张表的同一条数据,都是在事物里访问

总是出现死锁的情况,以前没有用 select for update,总是锁在update语句上

最近改成了select for update,现在又会锁在这条语句上

这种问题如何很好的解决?

加载中
0
如风随影
如风随影
可能跟事务中的锁机制有关!!
0
瑞新
瑞新

加锁行为子句

 

加锁行为子句相对比较容易理解。这里分别介绍。

 

Nowait子句

 

当我们进行for update的操作时,与普通select存在很大不同。一般select是不需要考虑数据是否被锁定,最多根据多版本一致读的特性读取之前的版本。加入for update之后,Oracle就要求启动一个新事务,尝试对数据进行加锁。如果当前已经被加锁,默认的行为必然是block等待。

 

使用nowait子句的作用就是避免进行等待,当发现请求加锁资源被锁定未释放的时候,直接报错返回。

 

对应的还有就是wait子句,也就是默认的for update行为。一旦发现对应资源被锁定,就等待blocking,直到资源被释放或者用户强制终止命令。

 

 

wait子句还存在一个数据参数位,表示当出现blocking等待的时候最多等待多长时间。单位是秒级别。

SQL> select * from emp for update wait 3;

 

select * from emp for update wait 3

 

ORA-30006:资源已被占用;执行操作时出现WAIT超时

 

for update的使用

 

在日常中,我们对for update的使用还是比较普遍的,特别是在如pl/sql developer中手工修改数据。此时只是觉得方便,而对for update真正的含义缺乏理解。

 

For updateOracle提供的手工提高锁级别和范围的特例语句。Oracle的锁机制是目前各类型数据库锁机制中比较优秀的。所以,Oracle认为一般不需要用户和应用直接进行锁的控制和提升。甚至认为死锁这类锁相关问题的出现场景,大都与手工提升锁有关。所以,Oracle并不推荐使用for update作为日常开发使用。而且,在平时开发和运维中,使用了for update却忘记提交,会引起很多锁表故障。

 

那么,什么时候需要使用for update?就是那些需要业务层面数据独占时,可以考虑使用for update。场景上,比如火车票订票,在屏幕上显示邮票,而真正进行出票时,需要重新确定一下这个数据没有被其他客户端修改。所以,在这个确认过程中,可以使用for update。这是统一的解决方案方案问题,需要前期有所准备。

 

0
IdleMan
IdleMan
很感兴趣啊。。Oracle啥版本
0
酒逍遥
酒逍遥
不要用 悲观锁..用乐观锁吧
0
hulubo
hulubo

一般来说交叉更新导致死锁的问题比较常见。

能不能把2个事务中执行的sql拿出来看看?

0
z
zhxh007

引用来自“酒逍遥”的答案

不要用 悲观锁..用乐观锁吧
同意
0
yybf000
yybf000

如果对hibernate用的不是太熟,还是介意你用ibatis,这样数据的操作,你全可以自己编写,定义

 

返回顶部
顶部