#oracle #transactions #isolation-level
#Oracle #транзакции #уровень изоляции
Вопрос:
У меня есть процедура, в которой a создает кредиты для клиентов. Клиенты могут получить только 10000 максимум. Сначала я читаю сумму, запрошенную клиентом по старым кредитам, если клиент запросил более 10000, я выдаю ошибку, иначе я вставляю новый кредит.
create or replace NONEDITIONABLE PROCEDURE CREATE_LOAN
(
p_client_id INT,
p_requested_loan_amount DECIMAL
)
IS
v_available_amount DECIMAL DEFAULT 0;
BEGIN
--Get available amount for the client( Clients cant require more thant 10000)
SELECT 10000 - COALESCE(SUM(l.amount), 0) INTO v_available_amount
FROM loans l
WHERE l.client_id = p_client_id
AND (l.state_id = 1 OR l.state_id = 2);
--If the cliente requested more than 10000 in older loans raise error
IF p_requested_loan_amount > v_available_amount
THEN
raise_application_error( -20001, 'Not enough available amount.' );
END IF;
--Else insert new loan
INSERT INTO loans (amount, state_id, client_id)
VALUES(p_requested_loan_amount, 1, p_client_id);
END;
Как я могу предотвратить одновременное считывание двух одновременных транзакций со старыми кредитами одновременно, и обе считают, что у них есть доступная сумма до их вставки. Если бы я использовал Sql Server, я мог бы повысить уровень изоляции, и это предотвратило бы проблему, но в Oracle это работает по-другому.
Ответ №1:
В инструкции SELECT используйте предложение FOR UPDATE . Это приведет к блокировке строки и остановит блокировку этой строки другой транзакцией.
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:4530093713805
Комментарии:
1. Почему сериализуемый уровень изоляции не предотвращает это в oracle?
2. Кажется, что в oracle вы не «видите» регистры чтения phatom.