UTF.COM.CN

利用悲观锁解决数据库死锁

作者:佚名 | 来源:网络 | 添加时间:2006-02-28 22:44:05 | 人气:1752

利用悲观锁解决数据库死锁

这边讲述的数据库死锁是由于查询条件顺序不对而造成的一类,
主要是两个线程在同时对一个数据库表进行操作时,出现了下列情况,
假设一个数据库表内有5行数据,
线程1需要对1-4行数据进行update操作,
而线程2需要对2-5行数据进行update操作,
但是由于操作的顺序调整的不正确,
线程1是对数据行1,2,3,4这样的顺序操作,并且加入batch的,
而线程2是对数据行5,4,3,2这样的顺序操作的,并且加入batch,
于是锁就这样产生了:
当线程1的executeBatch进行批量update时,
锁住了123行数据,开始操第4行数据时,
此时线程二的executeBatch正当操作完第4行数据,准备操作第3行数据,
而此时线程2则拿着4,5行数据的锁,并且不会释放。
于是线程1发现第4行数据的锁已经被占用,便开始等待这个锁的释放,
对于batch操作来说,在没有完成整个事务时,
线程1不会释放对1,2,3行数据的锁的拥有权,
同样2号线程也在等待1线程释放3号数据的锁,同样等待,
这个相互等待的过程将不会结束,直到数据库有额外的机制来回滚一个操作。
当然,这就意味着这两个操作里面有一个就失败了。

当然,最好的解决办法就是调整操作顺序使其(操作顺序)一致,
但是当这个里面有错总复杂的问题的时候,比如有时多个线程之间对同一个表操作,
或者多个线程操作多个表时,理起来就会变得麻烦。
这边还有一个方案,对于oracle或者sql server这类支持主观加载悲观锁的数据库,
可以利用这个特性来手动实现数据库批量操作的事务锁。
针对oracle,可以用select ... for update来加载悲观锁,
比如需要对于某个字段进行update,则可以用select语句在末尾加上for update把这个字段锁住,
然后进行batch的操作。
这边需要注意的是,
1.对于开始使用select ... for update前,必须将autoCommit设置成false,
2.完成一个update后,必须commit这个事务以便释放这批锁。
3.操作时要保证数据库表没有其他死锁,否则也会引起一些问题(sqlplus操作需要commit掉)
用这个方法,对于锁的控制主权更多,一旦出问题时,调试更加简便,
缺点是效率还是一个大问题,毕竟对于大规模数据来说,还是调整执行顺序是首选,
我这个只能算是个旁门左道,嘿嘿。
责任编辑:冬天来了
【字号: 】【去论坛讨论】【发表评论】【打印本文】【告诉好友】【关闭窗口
网友评论(评论内容只代表网友观点,与本站立场无关!)

姓名:

验证码: 点击刷新