加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SKIP LOCKED 子句的使用

(2013-01-13 21:04:26)
标签:

oracle

lock

分类: 小记

程序中处理并发问题时,经常需要用 for update 字句来锁住将要处理的行,以免同一行数据被多个程序同时处理,而导致数据一致性出现问题。

 

但是for update有一个缺陷,就是将导致不必要的等待。

 

举例来说:

我们有一张事务处理表 my_transactions,其中有一列status,如果为1,则表示该行数据等待处理。

 

我们的程序开头可以写成这样:

selec * from my_transactions where status = 1 for update;

这样就将所有 status为1的数据锁定,如果同时有另一个相同的程序在运行,那么新的程序在刚开始运行时,就会阻塞在

selec * from my_transactions where status = 1 for update;

这条语句上。

 

到目前为止,听起来一切正常。

 

然而考虑稍微复杂一些的情况,假设my_transactions表中目前有1000条待处理的数据,

1.程序A1开始运行,1000条status=1的数据已经被锁定。

2.my_transactions表中新增了10000条status=1的数据等待处理。

3.相同的程序A2开始运行,但是当其刚开始运行至

  selec * from my_transactions where status = 1 for update;

  时,便被阻塞了。因为A1还未运行完成,有1000条数据被A1锁定着。

 

问题出现了,虽然my_transactions表中有10000条待处理的新记录,A2却还是毫无必要地被A1阻塞。这样的阻塞是没有道理的。

 

那么如何既保证数据一致性不被破坏,同时又避免上述例子中的情况呢?

 

skip locked 特性就是为了这种场合而诞生的。

 

我们将

selec * from my_transactions where status = 1 for update;

改为

selec * from my_transactions where status = 1 for update skip locked;

 

回到之前的例子

1.程序A1开始运行,1000条status=1的数据已经全部被锁定。

2.my_transactions表中新增了10000条status=1的数据等待处理。

3.相同的程序A2开始运行,当其刚开始运行至

  selec * from my_transactions where status = 1 for update skip locked;

  时,Oracle发现共有11000条 satus = 1的数据,但是其中的1000条已经被A1锁定了,这时Oracle 发现使用了 skip locked 提示,于是它自动将未被锁定的10000条新插入的数据筛选了出来。

 

 

这样,我们既保证了数据一致性不被破坏,同时又避免了不必要的锁定等待。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有