Чтение - проверка - запись флага в базу данных

В программе мы можем контролировать несколько процессов, обращающихся к БД, с помощью синхронизированного блока. Какой подход мы можем использовать для сценария ниже.

  • Считайте значение столбца из базы данных - скажем, flag
  • Если flag - это zero, обновите столбец флагов как One
  • Выполните набор обработки в приложении, которое должно быть защищено флаг (другой экземпляр приложения не должен выполнять такого рода операции, пока flag не будет установлен в ноль)
  • Обновите столбец flag еще раз до zero

Существует несколько экземпляров приложений, выполняющих указанную выше операцию, указывающую на одну и ту же таблицу БД. Как мы можем синхронизировать этот процесс между экземплярами приложения?

Исследование выполнено

Прочтите о блокировке таблиц БД и блокировках строк, но в моем случае чтение и запись - это две операции, которые должны работать как единица работы из другого экземпляра приложения.

Существуют разные способы интерпретации вашего требования, и для них есть разные решения. Так что уточните, пожалуйста, свой вопрос. Действует ли «набор обработки» на таблицу с flag или на другие таблицы / наборы данных? Есть ли только один экземпляр flag, который применяется повсеместно во всем приложении, или есть несколько экземпляров флага, которые идентифицируют несколько "наборы обработки"?

APC 08.06.2018 16:01

Столбец флага универсален. Если какое-либо приложение установило флаг в 1, другое приложение не должно выполнять никаких операций.

mahesh 08.06.2018 16:04

Итак, что вы хотите, чтобы произошло, если какой-то другой процесс попытается установить флаг, пока кто-то другой его обрабатывает?

APC 08.06.2018 16:05

Может быть, посмотрите ВЫБРАТЬ ... ДЛЯ ОБНОВЛЕНИЯ ...

OldProgrammer 08.06.2018 16:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
4
184
1

Ответы 1

По моему опыту, вы не можете безопасно использовать значения в столбцах как способ «заблокировать» вещи. Если вам нужно сгенерировать блокировку, я предлагаю вам использовать подпрограммы из пакета 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;

Удачи.

Хороший пример Боб. К сожалению, я не верю, что это соответствует его требованию "чтение и запись - это две операции, которые должны работать как единица работы из разных экземпляров приложения.". Его требования несколько сбивают с толку: он не хочет, чтобы другие экземпляры приложения могли что-то делать, но он хочет, чтобы несколько экземпляров приложения могли что-то делать. Как узнать, какие экземпляры подходят для обновления, а какие нет. Если только несколько экземпляров не запущены в вашем разделе Делайте то, что вам нужно, исключительно здесь.

Brian Leach 08.06.2018 22:54

Другие вопросы по теме