Oracle的AQ可用于消息处理, 可有一个或几个消息产生者将不同的消息插入到AQ表中, 然后由多个进程来获取并处理这些消息, 虽然这儿的解释很简单, 但要实现一个可靠具有事务功能的消息处理系统还是件不容易的事情. 在这儿我要讲的是当有多个消息处理进程时, Oracle是如何让他们能最快地并行地处理的?
这个问题可以简化为, 在一个表中有很多的记录(消息), 然后有很多进程来将这个表中的记录取出来, 进行处理后, 并在这个表中删除已经处理过的记录, 如果只有一两个这样的进程时, 可能什么事情也看不出来, 但是当有很多同样的进程来并行地处理这些记录时, 就会遇到数据库中常会遇到的Enqueue等待.
按照一般的处理方法可能会使用如下的代码:
declare
cursor msg is select ... from message_table
where rownum < n and .....;
begin
open msg;
loop
fetch msg into ....;
process_message;
delete message_table where pk=msg.pk;
exit when msg%notfound;
end loop;
close msg;
exception
when others then
rollback;
end;
/
当有很多进程并行运行这段代码时, 就有可能会出现很严重的Enqueue Wait, 在Oracle AQ的Dequeue过程中,使用了Skip Locked这样的关键字, 以跳过别其他进程锁住的记录, 更改后的代码如下:
declare
cursor msg is select ... from message_table
where rownum < n and ..... for update skip locked;
begin
open msg;
loop
fetch msg into ....;
process_message;
delete message_table where pk=msg.pk;
exit when msg%notfound;
end loop;
close msg;
exception
when others then
rollback;
end;
/
我是在研究AQ时顺便用SQL_TRACE去跟踪了一把才发现的, 一转眼已经是两年多以前的事了.
留言 (3)
很有用啊。要多推广~
Posted by yumianfeilong | Mar 1, 2007 10:11 AM
不知道这一次写清楚了没有?
Posted by anysql | Mar 1, 2007 10:30 AM
This sounds like a classic undocumented SELECT FOR UPDATE SKIP LOCKED command.
用着放心吗? 以后不支持了咋办...
Posted by zhu1 (木匠) | Mar 9, 2007 2:09 AM