有一些程序,比如系统监控工具,就应该是永远执行。这种情况下,就会需要人为的无限循环:
loop
data_gathering_procedure;
end loop;
由于持续的运行对cpu资源消耗严重,为了避免资源耗费殆尽,病保证数据收集过程尽可能有效的运行,
所以需要循环在运行中适当的暂停。
loop
data_gathering_procedure;
dbms_lock.sleep(10) ; //10秒内不作任何事情
end loop;
当然 ,那么我们又如何结束这种无限的循环呢?通常我们都是以存储过程形式运行,即便杀掉前台进程也不会终止后台进程。我们可以使用alter system kill session,但在某些版本的oracle中这个命令并不会杀掉一个卡在循环中的会话。
所以我们必须求助于操作系统的工具了,比如unix/linux平台的kill以及windows的orakill.exe.这些工具需要知道oracle的系统进程的ID,在V$SSEION和V$PROCESS中很容易查出。
当然我们还有更好的方法解决这个问题,在循环中插入一个“命令解释器”,然后通过数据库内置的进程间通讯机制来发送命令即数据库通道。
declare
pipename constant varchar2(12):='signaler';
result integer;
pipebuf varchar2(64);
begin
/* 创建一个指定名字的私有管道*/
result:=dbms_pipe.create_pipe(pipename);
loop
data_gathering_procedure;
dbms_lock.sleep(10);
/*检查管道是否有信息*/
if dbms_pipe.receive_message(pipename ,0)=0
then
dbms_pipe.unpack_message(pipebuf);
exit when pipebuf='stop';
end if;
end loop;
end;
现在可以构造一个简单地伙伴程序,这个程序只需要通过在管道中发送一个‘stop‘就可以终止这个循环的运行。
declare
pipename varchar2(12):='signaler';
result integer :=dbms_pipe.create_pipe(pipename);
begin
dbms_pipe.pack_message('stop');
end;