Załóżmy, że są dwie sesje, i dwa procesy w aplikacji, gdzie w jednym jest modyfikowana tabela A, a później jest modyfikowana tabela B, a w drugim procesie jest najpierw modyfikowana tabela A, a później jest modyfikowana tabela B.
Czyli procesy działają tak samo?
Procesy są różne, nieistotne, jakie konkretnie czynności wykonują, ale istotne, że są to modyfikacje danych w takiej kolejności, że mogą spowodować zakleszczenie. Chodzi o przykład, że jeden najpierw blokuje tabelę A, a potem tabelę B, a drugi proces dokładnie odwrotnie. Jest to najprostszy przypadek spełnienia jednego z warunków wystąpienia zakleszczenia.
O ile się nie mylę, w transakcji tabele są blokowanie sukcesywnie w miarę przebiegu transakcji i uruchomienie obu powyższych procesów naraz może spowodować wzajemne zablokowanie tych procesów (deadlock).
Rozpoczynasz transakcję.
Robisz modyfikacje na wszystkich tabelach.
Kończysz transakcję.
Robisz to dla obu procesów. I generalnie wszystko powinno być dobrze.
Bardzo małe jest prawdopodobieństwo, że oba procesy rozpoczną transakcję w idealnie w tym samym momencie. Jest tak niskie, że pomijalne.
Rozumiem, że w dobrze przemyślanym systemie to nie powinno się zdarzać, a jak się zdarza, to należy przemyśleć procesy i od nowa je zaimplementować uwzględniając kolejność blokowania tabel. Ale pytanie jest nie na temat projektowania przebiegu procesu i działania systemu, tylko na temat blokowania tabel.
W takim razie załóżmy, że proces "1" wysyła polecenia, istotne jest, żeby cały proces był w jednej transakcji:
begin transaction
update table A set xxx = xxx --Blokuje tabelę A
-- Jakaś logika biznesowa, która robi dużo select i obliczeń i trochę trwa
update table B set xxx = xxx --Blokuje tabelę B
commit --Odblokowuje najpierw tabelę B, a potem tabelę A
Proces "2" wysyła polecenia:
begin transaction
update table B set xxx = xxx --Blokuje tabelę B
-- Jakaś logika biznesowa, która robi dużo select i obliczeń i trochę trwa
update table A set xxx = xxx --Blokuje tabelę A
commit --Odblokowuje najpierw tabelę A, a potem tabelę B
Odpalamy proces "1" i w czasie jego trwania odpalamy proces "2". Zablokowanie jednej tabeli nastąpi w chwili wykonania pierwszego update, a zakleszczenie nastąpi w chwili dojścia do ostatniego update obu procesów.
Załóżmy, że proces "2" się lekko zmodyfikuje:
begin transaction
-- "Zablokuj tabelę A" -- Polecenie, o które się pytam, blokuje tabelę A
update table B set xxx = xxx --Blokuje tabelę B
-- Jakaś logika biznesowa, która robi dużo select i obliczeń i trochę trwa
update table A set xxx = xxx --Tabela A została wcześniej zablokowana, więc niczego nie blokuje
commit --Odblokowuje najpierw tabelę A, a potem tabelę B
Wtedy, jak się odpali "1", a później "2", to w chwili odpalenia 2 jest zablokowana tabela A, więc proces poczeka na odblokowanie tabeli "A", co nastąpi dopiero po zakończeniu procesu "1". W takich warunkach wystąpienie deadlock nie jest możliwe. W takim razie, jakie poleceniem SQL dokonuje się wstępnego blokowania tabeli? Jak widać, teoretycznie jedno polecenie może rozwiązać problem w istniejącym systemie bez konieczności przerabiania i testowania.