Единственият преносим начин да постигнете съгласуваност между стаите и таговете и да гарантирате, че стаите никога не се връщат, след като са били изтрити, е да ги заключите с SELECT FOR UPDATE
.
Въпреки това в някои системи заключването е страничен ефект от контрола на паралелността и постигате същите резултати, без да указвате FOR UPDATE
изрично.
За да разреши този проблем, Thread 1 трябва да
SELECT id FROM rooms FOR UPDATE
, като по този начин предотвратява изтриването на Thread 2 отrooms
докато завърши Тема 1. Вярно ли е?
Това зависи от контрола за едновременност, който използва вашата система за бази данни.
-
MyISAM
вMySQL
(и няколко други стари системи) заключва цялата таблица за продължителността на заявката. -
В
SQL Server
,SELECT
заявките поставят споделени заключване на записите / страниците / таблиците, които са проверили, докатоDML
заявките поставят заключвания за актуализиране (които по-късно се повишават до изключителни или се понижават до споделени ключалки). Изключителните ключалки са несъвместими със споделените ключалки, така че илиSELECT
илиDELETE
заявката ще се заключи, докато друга сесия не бъде ангажирана. -
В бази данни, които използват
MVCC
(катоOracle
,PostgreSQL
,MySQL
сInnoDB
),DML
query създава копие на записа (по един или друг начин) и като цяло читателите не блокират писателите и обратно. За тези бази данни,SELECT FOR UPDATE
би било полезно:ще заключи илиSELECT
илиDELETE
заявка, докато друга сесия не се ангажира, точно кактоSQL Server
прави.
Кога трябва да се използва
REPEATABLE_READ
изолация на транзакциите срещуREAD_COMMITTED
сSELECT ... FOR UPDATE
?
Като цяло, REPEATABLE READ
не забранява фантомни редове (редове, които са се появили или изчезнали в друга транзакция, вместо да бъдат променени)
-
В
Oracle
и по-стариPostgreSQL
версии,REPEATABLE READ
всъщност е синоним наSERIALIZABLE
. По принцип това означава, че транзакцията не вижда промени, направени след като е започнала. Така че в тази настройка последнатаThread 1
query ще върне стаята, сякаш никога не е била изтрита (което може или не може да е това, което сте искали). Ако не искате да показвате стаите, след като са били изтрити, трябва да заключите редовете сSELECT FOR UPDATE
-
В
InnoDB
,REPEATABLE READ
иSERIALIZABLE
са различни неща:четци вSERIALIZABLE
режимът задава заключвания на следващия ключ на записите, които оценяват, ефективно предотвратявайки едновременнияDML
на тях. Така че нямате нужда отSELECT FOR UPDATE
в сериализиращ се режим, но се нуждаят от тях вREPEATABLE READ
илиREAD COMMITED
.
Имайте предвид, че стандартът за режимите на изолация предписва да не виждате определени странности във вашите заявки, но не дефинира как (със заключване или с MVCC
или по друг начин).
Когато кажа „не се нуждаете от SELECT FOR UPDATE
" Наистина трябваше да добавя "поради страничните ефекти от внедряването на определена база данни".