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