Как я могу использовать транзакционную базу данных для создания критического раздела? - PullRequest
1 голос
/ 01 июля 2011

Скажем, у меня есть 2 сервера, которые общаются с одной и той же транзакционной базой данных.

Я хочу настроить ее так, чтобы только один из этих двух серверов выполнял заданное действие по времени (по сути, используя базу данных для обеспечения синхронизации).).Из того, что я слышал, что-то вроде этого может работать:

Скажем, моя таблица TABLE имеет 2 столбца, ID и STATUS.Если я настрою код следующим образом:

update TABLE set STATUS = 'processing' where ID = 1234 and STATUS != 'processing'

if (weHaveModifiedAtLeastOneRow)
{
    // do critical section stuff here
    // This is code that we only want one server to run, not both.

    update TABLE set STATUS = 'free' where ID = 1234
}
else
{
    // We failed to get the lock, so do nothing
}

Будет ли это работать, или я здесь упускаю некоторые понятия?

1 Ответ

2 голосов
/ 02 июля 2011

Если вы хотите критический раздел, используйте dbms_lock.request . Вы можете получить многозначительный дескриптор блокировки, выделив уникальный, как это:

DBMS_LOCK.ALLOCATE_UNIQUE ( lockname =>  'MYAPP_' || ID, lockhandle => handle);
success := DBMS_LOCK.REQUEST(lockhandle => handle, timeout => 1);
if (success = 0) then
-- Do stuff
DBMS_LOCK.release(handle);
else
-- we waited a second and didn't got the lock.
end if;

Если вы предпочитаете это, вы можете применить хеш и оператор по модулю к id, чтобы спроецировать пространство значений id на известное количество блокировок, принимая (низкий) риск задержки несвязанных транзакций.

...