2

私のアプリケーションの現在のロックの概念は、2つのロックを取得してコードを実行することを前提としています。しかし、最初のロックハンドルを解放しようとすると、常にエラーが発生します。これを行う方法はありますか、それともdbms_lockを使用して一度に2つのロックを取得するのは間違っていますか?

よろしくお願いします!

DECLARE
  l_handle_1 VARCHAR2(128);
  l_handle_2 VARCHAR2(128);
  l_result NUMBER;
BEGIN

    -- >>> LOCK1
    dbms_lock.allocate_unique('lock_1', l_handle_1);
    l_result := dbms_lock.request(l_handle_1, dbms_lock.x_mode, 10, true);
    BEGIN

      -- >>> LOCK2
      dbms_lock.allocate_unique('lock_2', l_handle_2);
      l_result := dbms_lock.request(l_handle_2, dbms_lock.x_mode, 10, true);
      BEGIN

        /*
         * PLSQL-Code with both locks held
         */

        -- LOCK-2 release
        l_result := dbms_lock.release(l_handle_2);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 2');
        END IF;

        -- LOCK-1 release
        l_result := dbms_lock.release(l_handle_1);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 1');
        END IF;

      EXCEPTION
        WHEN OTHERS THEN
          l_result := dbms_lock.release(l_handle_2);
          IF (l_result > 0) THEN
            dbms_output.put_line('Fail 3');
          END IF;
          RAISE;          
      END;

    EXCEPTION
      WHEN OTHERS THEN
        l_result := dbms_lock.release(l_handle_1);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 4');
        END IF;
        RAISE;
    END;
END;
4

1 に答える 1

7

最初のロックハンドルに対してrelease_on_commit=TRUEを指定してdbms_lock.requestを呼び出してから、allocate_uniqueを呼び出します。locate_uniqueはコミットを実行するため、最初のロックを解放します。

次のようにコードを変更しても、エラーは発生しません。

DECLARE
  l_handle_1 VARCHAR2(128);
  l_handle_2 VARCHAR2(128);
  l_result NUMBER;
BEGIN


    dbms_lock.allocate_unique('lock_1', l_handle_1);
    dbms_lock.allocate_unique('lock_2', l_handle_2);

    -- >>> LOCK1
    l_result := dbms_lock.request(l_handle_1, dbms_lock.x_mode, 10, true);
    BEGIN

      -- >>> LOCK2
      -- dbms_lock.allocate_unique('lock_2', l_handle_2);
      l_result := dbms_lock.request(l_handle_2, dbms_lock.x_mode, 10, true);
      BEGIN

        /*
         * PLSQL-Code with both locks held
         */

        -- LOCK-2 release
        l_result := dbms_lock.release(l_handle_2);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 2');
        END IF;

        -- LOCK-1 release
        l_result := dbms_lock.release(l_handle_1);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 1');
        END IF;

      EXCEPTION
        WHEN OTHERS THEN
          l_result := dbms_lock.release(l_handle_2);
          IF (l_result > 0) THEN
            dbms_output.put_line('Fail 3');
          END IF;
          RAISE;          
      END;

    EXCEPTION
      WHEN OTHERS THEN
        l_result := dbms_lock.release(l_handle_1);
        IF (l_result > 0) THEN
          dbms_output.put_line('Fail 4');
        END IF;
        RAISE;
    END;
END;
于 2012-07-27T14:12:59.853 に答える