我正在使用DB2 11.5
.
我有一个存储过程,它将运行一些复杂的任务。 在运行任务之前,它将首先从日志表中检查作业是否已在运行,如果是,则发出SQLSTATE 75002
错误测量信号。
如果尚未运行,它将插入状态为RUNNING
的作业记录,然后运行任务。
完成后,它将状态更新为FINISHED
。
CREATE OR REPLACE PROCEDURE WORK.TEST_SP()
P1: BEGIN
if exists(select 1 from db2inst1.job_log where job='abc' and status='RUNNING' and date=current date) then
SIGNAL SQLSTATE '75002' SET MESSAGE_TEXT = 'Job abc is already running, please wait for it to finish';
end if;
insert into db2inst1.job_log values ('abc', 'RUNNING', current date);
commit;
-- Some complex tasks here
call dbms_lock.sleep(120);
update db2inst1.job_log set job_status='FINISHED' where job_name='abc' and job_date=current date
commit;
END P1
我的问题是,当用户按下在复杂任务运行时中止存储过程的ctrl-c
时,如何处理 sigint?
我希望它在发生ctrl-c
时更新job_status以ABORTED
,以便作业不会永远"运行"。
#Edit 1
用户在安装了 db2 客户机的本地机器上使用 Windows.bat
文件运行存储过程。
@echo off
@if ""%DB2CLP%""=="""" db2cmd /c /i /w ""%0"" && goto :EOF
db2 connect to mydb user db2inst1 using abc123
db2 "call WORK.TEST_SP()"
IF ERRORLEVEL 1 (echo Job failed) else (echo Job done)
db2 connect reset > nul
pause
如果您的 MS-Windows 批处理文件被 Control-C 或其他信号中断,则默认情况下,该应用调用的任何已启动/正在运行的存储过程将继续运行。 存储过程将不知道客户端应用程序已终止。因此,批处理文件 (cmd/bat) 将终止,但任何当前运行的存储过程将继续在 Db2 服务器上执行。
不能将操作系统信号直接发送到 Db2-LUW 存储过程,因为它们在后台的 Db2 服务器上运行,并且通常由与执行call
的用户标识不同的帐户拥有。
存储过程应有自己的条件处理程序、退出处理程序或撤消处理程序。通常,如果发生硬错误,而过程本身无法恢复,则希望发出rollback
。但是 Db2 本身会为特定的 sqlcode 发出回滚(例如 -911 )。
Db2-LUW 还具有应用程序在特定情况下可能使用的sysproc.cancel_work
过程。有关详细信息,请参阅知识中心。如果启用了 WLM(工作负载管理)或等效项,则存储过程受其资源消耗配置的约束,并且 WLM 还提供wlm_cancel_activity
例程。
在 SP.
Control 不会在强制调用方离开数据库、取消活动和某些其他条件(例如日志已满)时传递给 SP 中定义的异常处理程序。
因此,不要将任何标志/状态管理逻辑放入 SP 异常处理程序中。
存储过程是如何运行的?从命令行(db2
)?如果是,在哪些操作系统上?
例如,如果命令在 Linux 上从bash
运行,则可以在用户按 Ctrl-Cmyfunc
使用 Bash 中的trap myfunc SIGINT
来运行自定义 Bash 函数。 然后,myfunc
可以更改作业状态。
在Windows上,如果您从普通.bat
文件切换到Powershell,您将拥有更多控制权。一些相关的堆栈溢出问题:
- 批处理脚本,如果用户按 Ctrl+C 在退出之前执行命令
- 优雅地停在Powershell中