Не сме сами, част 4
Основно правило при многопотребителската работа е да си заключваш ресурсите, с които работиш. Едно здраво заключване може да спести много главоболия. За съжаление за да направиш добро заключване, трябва 1) да си осъзнал, че ти трябва, и 2) да знаеш как да го направиш 🙂
Повечето хора се сещат за select ... for update. Обаче има и други заключваници, които могат да помогнат на съвестния db developer. Единият вариант е Lock table. Ще използвам примера от част 2:
create or replace procedure Process_New_Data is
-- example code - not scalable!!!
begin
-- lock the log table, so none will be able to add/remove batches
lock table batch_log in exclusive mode;
-- process the loaded batches
insert /*+append*/
into prod_table
select -- do some processing
batch_id, get_something(column1, column2), calculate_something(column3, column4),
RANK() over(PARTITION BY column5, column6 order by column7) rn,
column8, column9, ...
from loader_table
where batch_id in (select batch_id
from batch_log
where processed = 0);
-- delete the rows from loader table
delete from loader_table
where batch_id in (select batch_id
from batch_log
where processed = 0);
-- mark the batches as processed
update batch_log
set processed = 1
where processed = 0;
commit;
end;
В случая още в началото на процедурата заключваме таблицата batch_log. Това означава, че никой няма да може да добавя, променя или премахва редове от нея. :
– ако има сесия, която вкарва нови данни, при опит да направи insert – ще чака.
– ако има друга сесия, която изпълнява нашата процедура за обработка/преместване на данни – ще гръмне или ще чака, в зависимост от това дали ще дадем wait на заключването. Това е и една от причините този lock да се прави в самото начало, преди да сме свършили някаква друга работа.
Самото заключване се „отключва“ автоматично в с първия commit или rollback. За това точно този подход е неприложим в ситуации като описаната в част 1.
По-лошото е, че този подход е адски не-скалируем. Това е brute force на защитата. Докато не приключим с всичката работа, никой няма да може да работи по тази таблица (освен да select-ва). С други думи, заменили сме един проблем с друг. И сега проблема ще се прояви при натоварване с конкурентни сесии. Може да се каже, че сме по-добре: проблемът ще е ясен, няма да има случайни загуби или дублиране. Но си е проблем.
Интересна дилема: колкото повече (и по-рестриктивни) заключваници използваме, толкова по-зле понася товар едно приложение. Но ако не ги използваме, добрата саклируемост води до грешни данни. Някой да си е помислил, че има просто решение? 🙂
Sorry, the comment form is closed at this time.