I am using DB2 11.5.
I have a stored procedure that will run some complex tasks.
Before running the tasks, it will first check from a log table if the job is already running, if yes, it signal for SQLSTATE 75002 with error meesage.
If it is not already running, it will insert a record of the job with status RUNNING, then run the tasks.
When it finishes, it update the status to 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
My question is how do I handle sigint when user press ctrl-c that aborted the stored procedure when the complex tasks are running?
I want it to update the job_status to ABORTED when ctrl-c occurs so that the job will not be "running" forever.
#Edit 1
Users run the stored procedure with a windows .bat file on local machine with db2 client installed.
#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
If your MS-Windows batch file gets interrupted by a Control-C or other signal, then any already started/running stored-procedures invoked by that app will continue running by default. The stored procedure will be unaware that the client application has terminated. So your batch file (cmd/bat) will terminate but any currently running stored procedure will continue to execute on the Db2-server.
You cannot send operating-system signals directly to a Db2-LUW stored procedure, as they run on the Db2-server in the background and are usually owned by a different account than the userid performing the call.
Your stored-procedure should have its own condition handlers or exit handlers or undo handlers. Usually you want to issue a rollback if a hard error happens from which your procedure itself cannot recover. But Db2 itself will issue a rollback for specific sqlcodes (e.g. -911 ).
Db2-LUW also has a sysproc.cancel_work procedure which an application might use in specific situations. Refer to the Knowledge Centre for details. If WLM (workload management) or equivalent is enabled then stored procedures are subject to its configuration as regards resource consumption, and WLM also offers a wlm_cancel_activity routine.
There is no way to do this in SP.
Control is not passed to an exception handler defined in SP upon forcing a caller off the database, canceling activity and some other conditions (log full, for example).
So, don't put any flag / status management logic into SP exception handlers.
How is the stored procedure run? From the command line (db2)? If so, on what operating systems?
If, for instance, the command is run from bash on Linux, you can use trap myfunc SIGINT in Bash to run a custom Bash function myfunc if the user presses Ctrl-C. myfunc could then change the job status.
On Windows, you will have more control if you switch from plain .bat files to Powershell . Some related Stack Overflow questions:
batch script if user press Ctrl+C do a command before exiting
Gracefully stopping in Powershell
Related
I want to know how to write a shell script that access oracle database and check a procedure that executed earlier if it is succeeded or returned error
If you want to know about procedure that executed earlier (in a different session?), you can't, unless the results were persisted somehow. Oracle by itself doesn't store info about every procedure call.
If you just want to run and check the stored procedure immediately from the shell script, that's a standard pattern, use whenever sqlerror/oserror clause:
sqlplus [connection_string] <<-EOF
whenever oserror exit failure;
whenever sqlerror exit failure;
exec [stored_procedure];
EOF
if [[ $? != 0 ]]; then
echo "Procedure failed!"
exit 1
fi
->Reference
I've an assignment to run the command on Tandem by periodic time
I've work on Windows and Unix before and know that OS have there own schedule task but I cannot find one on Tandem
I've ask HPE support they mention that I must by a tool name "NetBatch" to make a schedule
now I come up with a solution by create job to run command like this
1.Run command
2.Wait time
2.Run command
4.Wait time
Have anyone here have experience with schedule task on Tandem please advice
Thanks
You can create a tacl script with a loop, add all commands you want in that loop with #DELAY at end of the loop so that the script waits till next iteration of loop
To add persistance to your script you can configure it under pathway as below:
RESET SERVER
SET SERVER MAXSERVERS 1
SET SERVER NUMSTATIC 1
SET SERVER PROGRAM $SYSTEM.SYS01.TACL
SET SERVER TMF OFF
SET SERVER IN $receive
SET SERVER ASSIGN TACLCSTM, $vol.subvol.taclin ==The script that you want to execute
SET SERVER OUT $vol.subvol.uroutfil ==Output printed from your script
ADD SERVER mytacl
You could switch to from Guardian to OSS and use crontab on tandem OSS
Yes you can insert wait between two [tandem advanced command language] TACL commands by entering some other command or using something from history like opening files.
dsply pr, prc310
cmprfile -28, today, range
cmprtime 00,23
dsply pr, prc310, diff
NOTE: The last code executes with a time difference of 3 seconds.
This will surely delay the simultaneous command from being executed at the same time.
I also faced the same situation, and followed above hack to get it rectified.
I'm attempting to use the TProcess unit to execute ssh to connect to one of my servers and provide me with the shell. It's a rewrite of one I had in Ruby as the execution time for Ruby is very slow. When I run my Process.Execute function, I am presented with the shell but it is immediately backgrounded. Running pgrep ssh reveals that it is running but I have no access to it whatsoever, using fg does not bring it back. The code is as follows for this segment:
if HasOption('c', 'connect') then begin
TempFile:= GetRecord(GetOptionValue('c', 'connect'));
AProcess:= TProcess.Create(nil);
AProcess.Executable:= '/usr/bin/ssh';
AProcess.Parameters.Add('-p');
AProcess.Parameters.Add(TempFile.Port);
AProcess.Parameters.Add('-ntt');
AProcess.Parameters.Add(TempFile.Username + '#' + TempFile.Address);
AProcess.Options:= [];
AProcess.ShowWindow:= swoShow;
AProcess.InheritHandles:= False;
AProcess.Execute;
AProcess.Free;
Terminate;
Exit;
end;
TempFile is a variable of type TProfile, which is a record containing information about the server. The cataloging system and retrieval works fine, but pulling up the shell does not.
...
AProcess.ShowWindow:= swoShow;
AProcess.InheritHandles:= False;
AProcess.Execute;
AProcess.Free;
...
You're starting the process but not waiting for it to exit. This is from the documentation on Execute:
Execute actually executes the program as specified in CommandLine, applying as much as of the specified options as supported on the current platform.
If the poWaitOnExit option is specified in Options, then the call will only return when the program has finished executing (or if an error occured). If this option is not given, the call returns immediatly[sic], but the WaitOnExit call can be used to wait for it to close, or the Running call can be used to check whether it is still running.
You should set the poWaitOnExit option in options before calling Execute, so that Execute will block until the process exits. Or else call AProcess.WaitOnExit to explicitly wait for the process to exit.
I created the following stored procedure:
CREATE PROCEDURE [dbo].[_StartWebcamStream]
AS
BEGIN
declare #command varchar(200)
set #command = 'C:\startStream.bat'
exec master..xp_cmdshell #command
END
for executing a the batch file startStream.bat. This batch contain the following code:
"C:\Program Files (x86)\VideoLAN\VLC\vlc.exe" -I dummy -vvv rtsp://mycamaddress/live_mpeg4.sdp --network-caching=4096 --sout=#transcode{vcodec=mp4v,fps=15,vb=512,scale=1,height=240,width=320,acodec=mp4a,ab=128,channels=2}:duplicate{dst=http{mux=asf,dst=:11345/},dst=display} :sout-keep}
The batch file is launched correctly, but the query continues to run until the vlc is stopped.
What can I do for stopping the query letting the vlc running?
DISCLAIMER: Don't run these examples in production!
SQL Server watches all processes spawned by xp_cmdshell and waits for them to finish. to see that you can just run this statement:
EXEC xp_cmdshell 'cmd /C "start cmd /K dir"'
This starts a command shell that in-turn starts another command shell to execute the dir command. The first shell terminates right away after spawning the second (/C switch) while the second executes the "dir" and then does not terminate (/K switch). Because of that second lingering process, even though the process that SQL Server started directly is gone, the query won't return. You cannot even cancel it. Even if you close the window in SSMS, the request continues to run. You can check that with
SELECT r.session_id, t.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
The NO_OUTPUT parameter does not help either:
EXEC xp_cmdshell 'cmd /C "start cmd /K dir"', NO_OUTPUT;
You will see the same "sticky" behavior.
The only way to get rid of these is to restart the computer or manually kill the processes (requires taskmanager to be executed as administrator). Restarting the SQL Server service does not stop the spawned processes.
As a solution you can use the SQL Agent. It has a "Operating System (CmdExec)" step type that you can use to run your program. You can create the job and then start it using sp_start_job.
Either way, your process actually needs to finish at some point. Otherwise you will create a pile of process-"bodies" that will cause performance problems in the long run.
Any ideas on how to accomplish this?
USE [db_name]
BEGIN TRANSACTION
...TONS OF INSERTS
COMMIT;
RAISERROR (..) WITH NOWAIT; //If error continue with next batch
BEGIN TRANSACTION
...TONS OF INSERTS
COMMIT;
RAISERROR (..) WITH NOWAIT;
...
Use the -V flag on the command-line. If you set a sufficiently large enough value (e.g 17), even fairly severe errors will not stop the script.
e.g. sqlcmd ... -V 17 -i MyFile.sql
I will assume that you know what you're doing when you do this and are monitoring the error messages nonetheless.
You could go higher, up to level 25, but if you're getting errors between level 17 and 25, it's unlikely that you're going to be able to progress much because they tend to be caused by software or hardware errors on the server, rather than errors in the scripts you're inputting.
The behavior of batch interruption on error is a SQL Server (ie. backend) option and is governed by error severity. There is no way to change the server behavior, errors that interrupt the batch will always interrupt the batch, period.
The behavior of file continuation (run the next GO delimited batch after error) is a sqlcmd option and is controlled by the -b switch. By default is ON (meaning sqlcmd continues with the next batch).