设计出发点:
客户的流水线上会有N个工人,每个工人守在流水线的一个岔路上。
这时要对每个工人的作业量进行平衡划分,就需要对每个工人的手工剩余工作量进行统计,然后把新的作业流向手头工作量少的工人手里。
但假如统计的时间很长,流水线上的作业还没来得及分配岔口号,就会一直走到直线的岔口上,结果导致直线的岔口工作量很大,而其它岔口却很空闲。
这时候就可以强制SQL统计在限定时间内必须返回结果;如果限定时间不能得到查询结果,则可以忽略统计而考虑立刻分配随机的岔口号已分流新的工作量。
实现思路:
下面列出整个逻辑的实现过程:
1)模拟需要各种时间来得到结果的代码:
create or replace function send_number ( id number) return number as
v_result number;
begin
dbms_lock.sleep(id);
return id;
end send_number;
–可根据输入参数,来模拟需要固定时间的查询
如:下面查询就需要4秒来得到结果
SQL> select send_number(4) from dual;
SEND_NUMBER(4)
————–
4
Executed in 4.041 seconds
2)生成agent进程来执行发布的查询,agent进程从mc$agent中获得查询的语句,然后将结果传到mc$pipe管道中
create or replace procedure pipe_agent is
n number;
v_result number;
i_sql varchar2(4000);
begin
while 1>0 loop
i_sql:=null;
v_result:=dbms_pipe.receive_message( pipename => 'mc$agent');
if v_result=0 then
while dbms_pipe.next_item_type>0 loop
exit when i_sql is not null;
dbms_pipe.unpack_message(i_sql);
end loop;
end if;
dbms_output.put_line(i_sql);
execute immediate i_sql into n;
dbms_pipe.pack_message(item => n);
v_result:=dbms_pipe.send_message(pipename => 'mc$pipe');
end loop;
end pipe_agent;
3)函数pipe_return用于从mc$pipe中获得查询结果,如果在5秒内得到的话,就返回正常结果,如果超时,则返回空
即使之后查询得到
create or replace function pipe_return(i_sql varchar2) return number as
v_message number;
v_result number;
begin
v_message:=null;
dbms_pipe.purge(pipename => 'mc$agent');
dbms_pipe.purge(pipename => 'mc$pipe');
dbms_pipe.pack_message(item => i_sql);
v_result:=dbms_pipe.send_message(pipename => 'mc$agent');
v_result:=dbms_pipe.receive_message( pipename => 'mc$pipe',
timeout => 5);
if v_result=0 then
while dbms_pipe.next_item_type>0 loop
exit when v_message is not null;
dbms_pipe.unpack_message(v_message);
end loop;
/*else
如果超时,说明发布的SQL查询超时;
则发动另一个agent进程,以便以后的查询使用
这里作为演示,不涉及更复杂的情况
*/
end if;
dbms_output.put_line(v_message);
return v_message;
end pipe_return;
4)演示
打开一个会话,发送agent
begin
pipe_agent;
end;
另起一个会话,进行演示
注意:实际需要的查询sql语句,作为pipe_return的参数传入
a)不超时的查询
SQL> SQL> select pipe_return('select send_number(2) from dual') from dual;
PIPE_RETURN('SELECTSEND_NUMBER
——————————
2
Executed in 2.012 seconds
b)超时的查询
SQL> select pipe_return('select send_number(6) from dual') from dual;
PIPE_RETURN('SELECTSEND_NUMBER
——————————
Executed in 5.024 seconds