Advertisement
Sergey83

Oracle lock

Oct 26th, 2023 (edited)
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 4.10 KB | None | 0 0
  1. /*LOCK TABLE*****************************************************************************/
  2. DROP TABLE GLOBAL_LOCKS;
  3. CREATE TABLE GLOBAL_LOCKS
  4. (
  5.   lock_key    VARCHAR2(100) NOT NULL,
  6.   lock_info   VARCHAR2(2000),
  7.   token       VARCHAR2(2000) NOT NULL
  8. );
  9. -- Add comments to the table
  10. COMMENT ON TABLE GLOBAL_LOCKS
  11.   IS 'Таблица хранения глобальных блокировок';
  12. -- Add comments to the columns
  13. COMMENT ON column GLOBAL_LOCKS.lock_key
  14.   IS 'Ключ блокировки';
  15. COMMENT ON column GLOBAL_LOCKS.lock_info
  16.   IS 'Информация о блокировке';
  17. COMMENT ON column GLOBAL_LOCKS.token
  18.   IS 'Токен для получения возможности снятия блокировки';
  19. -- Create/Recreate primary, unique and foreign key constraints
  20. ALTER TABLE GLOBAL_LOCKS
  21.   add constraint GLOBAL_LOCKS_PK primary key (lock_key);
  22.  
  23. /*PACKAGE*****************************************************************************/
  24. CREATE OR REPLACE PACKAGE C_MD_LOCK IS
  25.  
  26.     FUNCTION tryLock(p_lock_key  IN VARCHAR2,
  27.                      p_lock_info IN OUT VARCHAR2) RETURN VARCHAR2;
  28.      
  29.     PROCEDURE unlock(p_token     IN VARCHAR2,
  30.                      p_lock_key  IN VARCHAR2);
  31.  
  32. END C_MD_LOCK;
  33. /
  34. CREATE OR REPLACE PACKAGE BODY C_MD_LOCK IS
  35.  
  36.   /** Distributed lock PLSQL implementation**/
  37.  
  38.   /**
  39.   Trying to acquire the lock.
  40.    
  41.   @p_lock_info - parameter is used to pass information about the lock being applied and to return information about the resulting holding lock,
  42.   regardless of whether the session succeeded in acquiring the lock or not.
  43.  
  44.   Returns token if success and NULL if not.    
  45.   **/
  46.   FUNCTION tryLock(p_lock_key IN VARCHAR2, p_lock_info IN OUT VARCHAR2)
  47.     RETURN VARCHAR2 IS
  48.     PRAGMA AUTONOMOUS_TRANSACTION;
  49.     v_token VARCHAR2(2000);
  50.   BEGIN
  51.     --First check
  52.     FOR rc IN (SELECT lock_info
  53.                  FROM GLOBAL_LOCKS
  54.                 WHERE lock_key = p_lock_key) LOOP
  55.       p_lock_info := rc.lock_info;
  56.       RETURN NULL;
  57.     END LOOP;
  58.  
  59.     --Locks the table to provide atomicity of check and insert operations
  60.     LOCK TABLE GLOBAL_LOCKS IN EXCLUSIVE MODE;
  61.  
  62.     --Second check
  63.     FOR rc IN (SELECT lock_info
  64.                  FROM GLOBAL_LOCKS
  65.                 WHERE lock_key = p_lock_key) LOOP
  66.       p_lock_info := rc.lock_info;
  67.       RETURN NULL;
  68.     END LOOP;
  69.  
  70.     v_token := SYS_GUID();
  71.  
  72.     INSERT INTO GLOBAL_LOCKS
  73.       (lock_key, lock_info, token)
  74.     VALUES
  75.       (p_lock_key, p_lock_info, v_token);
  76.  
  77.     COMMIT;
  78.     RETURN v_token;
  79.   EXCEPTION
  80.     WHEN OTHERS THEN
  81.       ROLLBACK;
  82.       RAISE_APPLICATION_ERROR(-20200,
  83.                               'Error in function "C_MD_LOCK.tryLock" ' ||
  84.                               DBMS_UTILITY.format_error_backtrace || ' ' ||
  85.                               SQLERRM);
  86.   END tryLock;
  87.  
  88.   /**
  89.     Attempts to release this lock by token.
  90.   **/
  91.   PROCEDURE unlock(p_token IN VARCHAR2, p_lock_key IN VARCHAR2) IS
  92.     PRAGMA AUTONOMOUS_TRANSACTION;
  93.   BEGIN
  94.     DELETE FROM GLOBAL_LOCKS
  95.      WHERE lock_key = p_lock_key
  96.        AND token = p_token;  
  97.     COMMIT;
  98.   EXCEPTION
  99.     WHEN OTHERS THEN
  100.       ROLLBACK;
  101.       RAISE_APPLICATION_ERROR(-20200,
  102.                               'Error in function "C_MD_LOCK.unlock" ' ||
  103.                               DBMS_UTILITY.format_error_backtrace || ' ' ||
  104.                               SQLERRM);
  105.   END unlock;
  106. END C_MD_LOCK;
  107. /
  108. /*TESTS*****************************************************************************/
  109. --lock
  110. DECLARE
  111.   v_token     VARCHAR2(2000);
  112.   v_lock_key  VARCHAR2(250) :='PROCESS_OKATO';
  113.   v_lock_info VARCHAR2(250) :='Импорт OKATO';
  114. BEGIN
  115.   -- Call the function
  116.   v_token := C_MD_LOCK.tryLock(p_lock_key => v_lock_key,
  117.                                p_lock_info => v_lock_info);
  118.  
  119.   DBMS_OUTPUT.put_line('token='||v_token );
  120. END;
  121. /
  122. --unlock
  123. DECLARE
  124.   v_token     VARCHAR2(2000) := '<token>';
  125.   v_lock_key  VARCHAR2(250)  :='PROCESS_OKATO';
  126. BEGIN
  127.   -- Call the procedure
  128.   C_MD_LOCK.unlock(p_token => v_token,
  129.                    p_lock_key => v_lock_key);
  130. END;
  131. /
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement