В общем, есть два подхода к проблеме
Вариант 1: пессимистическая блокировка
В этом сценарии вы пессимистичны, поэтому блокируете строку втаблица, когда вы выбираете его.Когда пользователь запрашивает таблицу Contracts
, он делает что-то вроде
SELECT *
FROM contracts
WHERE contract_id = <<some contract ID>>
FOR UPDATE NOWAIT;
Кто бы ни выбрал запись первым, она заблокирует ее.Любой, кто выберет секунду записи, получит ошибку ORA-00054, которую приложение затем поймает и сообщит им, что другой пользователь уже заблокировал запись.Когда первый пользователь завершает свою работу, он вводит свой INSERT в таблицу Contract_Acceptance
и фиксирует свою транзакцию.Это снимает блокировку строки в таблице Contracts
.
Вариант 2: оптимистическая блокировка
В этом сценарии вы с оптимизмом полагаете, что оба пользователяне будет конфликтовать, поэтому вы не заблокируете запись изначально.Вместо этого вы выбираете необходимые данные вместе со столбцом Last_Updated_Timestamp
, который добавляете в таблицу, если он еще не существует.Что-то вроде
SELECT <<list of columns>>, Last_Updated_Timestamp
FROM Contracts
WHERE contract_id = <<some contract ID>>
Когда пользователь принимает контракт, перед выполнением INSERT
в Contract_Acceptance
он выдает UPDATE
по контрактам
UPDATE Contracts
SET last_updated_timestamp = systimestamp
WHERE contract_id = <<some contract ID>>
AND last_update_timestamp = <<timestamp from the initial SELECT>>;
Первый человек, которыйсделать это обновление будет успешно (оператор будет обновлять 1 строку).Второй человек, который сделает это, обновит 0 строк.Приложение обнаруживает тот факт, что обновление не изменило ни одной строки, и сообщает второму пользователю, что кто-то другой уже обработал строку.
В любом случае
Вв любом случае вы, вероятно, захотите добавить ограничение UNIQUE
в таблицу Contract_Acceptance
.Это обеспечит наличие только одной строки в таблице Contract_Acceptance
для любого заданного Contract_ID
.
ALTER TABLE Contract_Acceptance
ADD CONSTRAINT unique_contract_id UNIQUE (Contract_ID)
Это вторая линия защиты, которая никогда не понадобится, но защищает вас в случае применениянеправильно реализует свою логику.