Не сме сами, част 4
Dec 17th, 2009 by yavor
Основно правило при многопотребителската работа е да си заключваш ресурсите, с които работиш. Едно здраво заключване може да спести много главоболия. За съжаление за да направиш добро заключване, трябва 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-ва). С други думи, заменили сме един проблем с друг. И сега проблема ще се прояви при натоварване с конкурентни сесии. Може да се каже, че сме по-добре: проблемът ще е ясен, няма да има случайни загуби или дублиране. Но си е проблем.
Интересна дилема: колкото повече (и по-рестриктивни) заключваници използваме, толкова по-зле понася товар едно приложение. Но ако не ги използваме, добрата саклируемост води до грешни данни. Някой да си е помислил, че има просто решение?