Db2

Db2

Where DBAs and data experts come together to stop operating and start innovating. Connect, share, and shape the AI era with us.


#Data


#Data
 View Only

Suspending a session using a SLEEP procedure 

Tue March 10, 2020 07:34 PM

Posted by: Serge Rielau

In this post I want to introduce a handy procedure which can be used to suspend a session for a specified amount of time.  A naive approach to wait is to simply execute a tight loop in a stored procedure such as this:

--#SET TERMINATOR @
CREATE OR REPLACE PROCEDURE SLEEP(seconds INTEGER)
BEGIN
  DECLARE end TIMESTAMP;
  SET end = CURRENT TIMESTAMP + seconds SECONDS;
wait:  LOOP
    IF CURRENT TIMESTAMP >= end THEN LEAVE wait; END IF;
  END LOOP wait;
END
@
--#SET TERMINATOR ;

VALUES CURRENT TIMESTAMP;
1
--------------------------
2012-01-14-13.30.24.593000

  1 record(s) selected.

CALL SLEEP(5);
  Return Status = 0

VALUES CURRENT TIMESTAMP;
1
--------------------------
2012-01-14-13.30.29.609000

  1 record(s) selected.
Sometimes naive works. Here it is definitely not.
The problem is that the LOOP will consume CPU while waiting. That is not acceptable.
You can test this out yourself by profiling the procedure using the SQL PL Profiler discussed earlier.
 
A better way is to really suspend the thread and thus allowing DB2 to do other work with the CPU.
The C language provides a sleep(sec) function on Unix and Sleep(msec) on Windows. 
There is also a Sleep() on Java.
Just for the fun of it let's use C today. 
  1. Ensure you have a C-compiler.
    On Linux you can use gcc which is free. On Windows Microsoft also provides a Visual Studio Express version for download.
  2. Open a shell and cd to the ...\sqllib\samples\c directory
    On Windows I open the Visual Studio command prompt to pick up the environment..
  3. Write the following file named sleep.c:
    #define win

    #ifdef win
      #include <windows.h>
    #else
      #include <unistd.h>
    #endif

    #include <sqludf.h>
    #include <sqlca.h>

    /*************************************************************************
    *  function sleep: Sleep for at least seconds
    *
    *     inputs :   seconds to sleep 
    **************************************************************************/

    #ifdef __cplusplus
    extern "C"
    #endif

     SQL_API_RC SQL_API_FN sleep_sec(
         SQLUDF_INTEGER   *sec,
         SQLUDF_SMALLINT  *secNullInd,
         SQLUDF_TRAIL_ARGS)
    {
     if (*secNullInd != -1 && sec > 0)
      {
    #ifdef win
        Sleep(*sec * 1000);
    #else
        sleep(*sec);
    #endif
      }
      return (0);
    }
  4. On Windows leave the file as is. On Linux or Unix   comment out the first line "//#define win"
  5. On Windows write the following file named sleep.def:
    LIBRARY SLEEP
    EXPORTS
    sleep_sec
    On Linux or Unix write the following file named sleep.exp instead:
    sleep_sec
  6. Execute: bldrtn sleep
    bldrtn will compile, link and finally copy the executable to ...\sqllib\function 
  7. If you are on windows double check that either the LIB or LIBPATH  contains ...\sqllib\function
  8. Now go to the CLP, connect to the database and create the function there:
    db2 -t

    CONNECT TO <dbname>;

    CREATE OR REPLACE PROCEDURE SLEEP(SECONDS INTEGER)
    SPECIFIC SLEEP
    NO SQL DETERMINISTIC NO EXTERNAL ACTION FENCED
    EXTERNAL NAME 'sleep!sleep_sec' LANGUAGE C PARAMETER STYLE SQL;
Try it out:
VALUES CURRENT TIMESTAMP;

1
--------------------------
2012-01-14-13.56.31.671000

  1 record(s) selected.

CALL SLEEP(5);

  Return Status = 0

VALUES CURRENT TIMESTAMP;

1
--------------------------
2012-01-14-13.56.36.687000

  1 record(s) selected.
 If you have an Oracle background you can create a DBMS_LOCK module for comfort:
CREATE OR REPLACE MODULE DBMS_LOCK; 

ALTER MODULE DBMS_LOCK PUBLISH PROCEDURE SLEEP(seconds INTEGER)
  SPECIFIC SLEEP
NO SQL DETERMINISTIC NO EXTERNAL ACTION FENCED
EXTERNAL NAME 'sleep!sleep_sec' LANGUAGE C PARAMETER STYLE SQL;

#Db2

Statistics
0 Favorited
6 Views
0 Files
0 Shares
0 Downloads