Недавно у меня была задача, согласно которой мне нужно было иметь определенную функциональность блокировки. Конкретное было связано с:
- Транзакция, которая обновлялась
стол был распределен, поэтому у меня не было
контролировать его,
- В течение дня
тысячи неблокирующих транзакций
должны быть поддержаны одновременно,
давайте назовем их «общими» операциями,
- Каждая «общая» операция обновляла строки в определенной «ветви» («LDN», «NY», «LA» ...),
- Один раз в день есть «мастер»
операции для каждой ветви, которые происходят по разному, на разных ветках,
- Во время основной операции нет
могут произойти «общие» операции в этой ветви.
- Когда операция «master» запускается
должен ждать текущего «генерала»
операция по предоставленному завершению филиала,
которые были в системе до того, как прибыла операция «master».
- Во время обработки 'master' в определенной ветви, все остальные ветви могут быть
обновлен.
Для архивации я создал таблицу Oracle DB
create table BRANCH_LOCK(
BRANCH VARCHAR2(10),
FLAG VARCHAR2(1),
CONSTRAINT "PK_BRANCH_LOCK" PRIMARY KEY ("BRANCH")
)
Поддерживались следующие функции для различных операций:
Для «общих» операций:
1. In the same XA transaction each operation locks BRANCH_LOCK table
in SHARE mode,
2. After locking it checks FLAG, on updated branch,
1. If flag is 'Y', that means that currently 'master'
operation is in progess, so Exception is thrown,
and no further processing is done;
2. If flag is 'N' than everything is OK, and general processing is done;
Для основной операции:
- Когда приходит операция 'master', я запускаю отдельную транзакцию, которая:
- Блокировка таблицы BRANCH_LOCK в режиме EXCLUSIVE, которую транзакция не может получить, пока в этой таблице есть блокировка режима SHARE в другой транзакции (таким образом, я гарантирую, что операция «master» начнется после завершения всех текущих «общих» операций, хотя ждет транзакций по всем веткам
закончить, не только указанную)
- Устанавливает флаг для ветви на 'Y'
(Таким образом, я гарантирую, что не будет «общих» транзакций, пока «мастер»
операция обработки),
- Во входящей транзакции я изменяю флаг в таблице на 'N', поэтому после
он фиксирует BRANCH_LOG таблица будет иметь
соответствующее значение в столбце FLAG, и система будет
уметь обрабатывать «общее»
операции снова.
Это еще не было в производстве, так что мне интересно, есть ли лучшее решение для этого,
и есть ли еще недостатки, кроме описанного?
Некоторые обновления, о которых я не упоминал:
- Операция «Master» работает с результатами «общих» операций, поэтому крайне важно, чтобы ни одна «общая» операция не терялась во время обработки «master», поэтому текущая «общая» операция должна завершиться, прежде чем master операция начала обработки.
- Несколько «общих» операций в одной и той же ветке происходят каждую секунду, около 3000 операций в секунду,
- Для ветви может выполняться только одна «главная» операция, одновременно могут обрабатываться несколько «основных» операций в разных филиалах.