读 - 检查 - 将标志写入数据库

时间:2018-06-08 13:48:51

标签: java database oracle locking

在程序中,我们可以使用Synchronized块控制多个进程访问DB。我们可以在下面的场景中使用什么方法。

  • 从数据库中读取列值 - 比如flag
  • 如果flagzero,则将标记列更新为One
  • 应用程序中应该受标志保护的处理集(应用程序的其他实例在flag设置为零之前不应该执行此类操作)
  • 再次将列flag更新为zero

有多个应用程序实例执行上述操作,指向同一个DB表。我们如何跨应用程序实例同步此过程?

完成研究

了解数据库表锁和行锁,但在我的情况下,读写是两个操作,应该作为来自不同应用程序实例的工作单元

1 个答案:

答案 0 :(得分:0)

根据我的经验,您无法安全地使用列中值作为锁定"的东西。如果你需要生成一个锁,我建议你使用DBMS_LOCK包中的例程,例如:

DECLARE
  strLock_handle  VARCHAR2(128);
  iResult         INTEGER;
  excpAllocate    EXCEPTION;

  PRAGMA EXCEPTION_INIT(excpAllocate, -20000);
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE(lockname   => 'YOUR LOCK NAME',
                            lockhandle => strLock_handle);

  iResult := DBMS_LOCK.REQUEST(lockhandle        => strLock_handle,
                               lockmode          => DBMS_LOCK.X_MODE,  -- exclusive mode
                               timeout           => DBMS_LOCK.MAXWAIT,
                               release_on_commit => FALSE);

  IF iResult = 0 THEN
    -- Do what you need to do exclusively here - nothing else will be able to enter this
    -- section as they'll stall on the DBMS_LOCK.REQUEST call above.

    DBMS_OUTPUT.PUT_LINE('This is a stupid piece of example code');

    -- Note: if we changed the RELEASE_ON_COMMIT parameter passed to DBMS_LOCK.REQUEST
    -- above to TRUE, the following COMMIT would release all locks held
    -- by this process for which RELEASE_ON_COMMIT was TRUE.

    COMMIT;

    -- Release the lock acquired above. This will allow one of the (possibly
    -- many) processes stalled on the DBMS_LOCK.REQUEST above to proceed.

    iResult := DBMS_LOCK.RELEASE(strLock_handle);
  ELSE
    -- Lock was not acquired. Reasons are:
    --   iResult   Reason
    --   1         Timeout
    --   2         Deadlock
    --   3         Parameter error
    --   4         Already own lock specified
    --   5         Illegal lock handle

    DBMS_OUTPUT.PUT_LINE('DBMS_LOCK.REQUEST failed - iResult = ' || iResult);
  END IF;
EXCEPTION
  WHEN excpAllocate THEN
    DBMS_OUTPUT.PUT_LINE('DBMS_LOCK.ALLOCATE failed : ' || SQLCODE || ' ' || SQLERRM);
END;

祝你好运。