`
coolsooner
  • 浏览: 1310910 次
文章分类
社区版块
存档分类
最新评论

《Oracle编程艺术》学习笔记(3)-SELECT FOR UPDATE SKIP LOCKED

 
阅读更多

考虑这么一个场景:等待处理的任务加入数据库某个表中,表的PROCESSED_FLAG列只有两个值:Y 和N。对于插入到表中的记录,该列值为N(表示未处理)。其他进程读取和处理这个记录时,就会把该列值从N更新为Y。

位图索引适用于低基数(low-cardinality)列,所谓低基数列就是指这个列只有很少的可取值。但是这里并不适合。采用位图索引,一个键指向多行,可能数以百计甚至更多。如果更新一个位图索引键,那么这个键指向的数百条记录会与你实际更新的那一行一同被有效地锁定。

可以在函数decode(process_flag, 'N', 'N')上创建一个基于函数的B*Tree索引,从而返回N或者NULL,利用完全为NULL的键不会放入B*Tree索引的特性,只在处理标志为N的记录上创建一个索引。
为了能够多个会话并行处理任务,在Oracle11g R1之后,可以利用SKIP LOCKED特性。它允许多个会话并发查找第一个未锁定,未处理的记录,然后锁定该记录进行处理。

下面举例说明。
创建表格,索引,添加数据:

现在表格T中的数据如下:
tony@ORA11GR2> select * from t;

ID PR PAYLOAD
---------- -- ----------------------------------------
1 Y payload 1
2 N payload 2
3 Y payload 3
4 N payload 4
5 Y payload 5

在2个会话中分别执行如下的过程块,

在第一个会话中,得到结果: I got row 2, payload 2
在第二个会话中,得到结果: I got row 4, payload 4

在Oracle11g R1之前,可以利用如下办法:

在2个会话中分别执行如下过程,也可以得到相同结果:


*如果使用高级排队(Advanced Queuing)并调用DBMS_AQ.DEQUEUE,解决方案会更容易。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics