关闭

数据库阻塞

388人阅读 评论(0) 收藏 举报

如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。这样一来,请求的会话会被阻塞,它会“挂起”,直至持有锁的会话放弃锁定的资源。几乎在所有情况下,阻塞都是可以避免的。实际上,如果你真的发现会话在一个交互式应用中被阻塞,就说明很有可能同时存在着另一个bug,即丢失更新,只不过你可能没有意识到这一点。也就是说,你的应用逻辑有问题,这才是阻塞的根源。

数据库中有5条常见的DML语句可能会阻塞,具体是:INSERT、UPDATE、DELETE、MERGE和SELECT FOR UPDATE。对于一个阻塞的SELECT FOR UPDATE,解决方案很简单:只需增加NOWAIT子句,它就不会阻塞了。这样一来, 你的应用会向最终用户报告,这一行已经锁定。另外4条DML语句才有意思。我们会分别分析这些DML语句,看看它们为什么不应阻塞,如果真的阻塞了又该如何修正。


阻塞的MergeUpdateDelete

在一个交互式应用中,可以从数据库查询某个数据,允许最终用户处理这个数据,再把它“放回”到数据库中,此时如果UPDATE或DELETE阻塞,就说明你的代码中可能存在一个丢失更新问题(如果真是这样,按我的说法,就是你的代码中存在bug)。你试图UPDATE(更新)其他人正在更新的行(换句话说,有人已经锁住了这一行)。通过使用SELECT FOR UPDATE NOWAIT查询可以避免这个问题,这个查询能做到:

q  验证自从你查询数据之后数据未被修改(防止丢失更新)。

q  锁住行(防止UPDATE或DELETE被阻塞)。

如前所述,不论采用哪一种锁定方法都可以这样做。不论是悲观锁定还是乐观锁定都可以利用SELECT FOR UPDATE NOWAIT查询来验证行未被修改。悲观锁定会在用户有意修改数据那一刻使用这条语句。乐观锁定则在即将在数据库中更新数据时使用这条语句。这样不仅能解决应用中的阻塞问题,还可以修正数据完整性问题。

由于MERGE只是INSERT和UPDATE(如果在10g中采用改进的MERGE语法,还可以是DELETE),所以可以同时使用这两种技术。

该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7819次
    • 积分:115
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:11篇
    • 译文:0篇
    • 评论:0条
    文章分类