内容纲要
概要描述
由于我们的PLSQL是运行在HiveServer端的session之中,当一条PLSQL语句尚未结束并且会运行很长时间的时候,可能客户端已经Ctrl+C杀掉自己了,而Server端由于还在执行PLSQL,无法侦听到客户端死掉,这样这个session中的PLSQL会变成类似僵尸进程。虽然客户端已经决定放弃这次执行,但该PLSQL依然会继续执行到结束,设想其中如果有大量的SQL语句执行或者干脆有个死循环,会耗费大量的Server端资源。
详细说明
1. 执行测试plsql块
--结合睡眠函数和for循环构造一个执行时间稍长的plsql
BEGIN
FOR i IN 1..10 LOOP
put_line(i||' '||to_char(sysdate,'yyyy-MM-dd HH:mm:ss'))
dbms_lock.sleep(10)
END loop
END
2. 查看正在运行的PLSQL
这条命令会显示session id和PLSQL语句,使用者需要从中找到自己想要终止的PLSQL的session id;
> PS PLSQL;
f87ef49d-5d4d-437e-a066-de2b58799239 : BEGIN
FOR i IN 1..10 LOOP
put_line(i||' '||to_char(sysdate,'yyyy-MM-dd HH:mm:ss'))
dbms_lock.sleep(10)
END loop
END
第一行的f87ef49d-5d4d-437e-a066-de2b58799239,就是\<SESSION_ID>
3. 终止正在运行的某条PLSQL
这条命令会发送一个终止信号给该session id中的PLSQL进程,待该进程下一次自检之时,发现有终止信号,则会结束自己;
-- KILL PLSQL ;
> kill PLSQL f87ef49d-5d4d-437e-a066-de2b58799239;
对应的plsql语句会抛出异常,EXECUTION FAILED: Task EXEC PLSQL error HiveException: [Error 40000] PLSQL process being killed.
自检是借鉴了操作系统中进程调度的思想。自检的粒度为一条PLSQL语句,也就是说每执行一条PLSQL语句会自检一次(也就是被OS调度一次)。所以如果有一条SQL语句执行时间特别长,那么KILL该进程后并不会马上生效,需要等到该SQL语句执行完毕才会发生自检并终止。这种情况如果确定要终止该进程,可到inceptor的4040页面去kill掉当前的SQL,这样外层PLSQL就会立即终止。