A única maneira portátil de obter consistência entre salas e tags e garantir que as salas nunca sejam retornadas após terem sido excluídas é bloqueá-las com
SELECT FOR UPDATE . No entanto, em alguns sistemas, o bloqueio é um efeito colateral do controle de simultaneidade e você obtém os mesmos resultados sem especificar
FOR UPDATE explicitamente.
Para resolver este problema, o Thread 1 deveSELECT id FROM rooms FOR UPDATE, evitando assim que o Thread 2 seja excluído deroomsaté que a Linha 1 seja concluída. Isso é correto?
Isso depende do controle de simultaneidade que seu sistema de banco de dados está usando.
-
MyISAMemMySQL(e vários outros sistemas antigos) bloqueia toda a tabela durante uma consulta.
-
EmSQL Server,SELECTconsultas colocam bloqueios compartilhados nos registros/páginas/tabelas que examinaram, enquantoDMLconsultas colocam bloqueios de atualização (que posteriormente são promovidos a bloqueios exclusivos ou rebaixados a bloqueios compartilhados). Bloqueios exclusivos são incompatíveis com bloqueios compartilhados, portanto,SELECTouDELETEA consulta será bloqueada até que outra sessão seja confirmada.
-
Em bancos de dados que usamMVCC(comoOracle,PostgreSQL,MySQLcomInnoDB), umDMLquery cria uma cópia do registro (de uma forma ou de outra) e geralmente os leitores não bloqueiam os escritores e vice-versa. Para esses bancos de dados, umSELECT FOR UPDATEseria útil:bloqueariaSELECTou oDELETEconsulta até que outra sessão seja confirmada, assim comoSQL Serverfaz.
Quando se deve usarREPEATABLE_READisolamento de transação versusREAD_COMMITTEDcomSELECT ... FOR UPDATE?
Geralmente,
REPEATABLE READ não proíbe linhas fantasmas (linhas que apareceram ou desapareceram em outra transação, ao invés de serem modificadas) -
EmOraclee anteriorPostgreSQLversões,REPEATABLE READé na verdade um sinônimo paraSERIALIZABLE. Basicamente, isso significa que a transação não vê as alterações feitas após o início. Portanto, nesta configuração, o últimoThread 1query retornará a sala como se nunca tivesse sido deletada (o que pode ou não ser o que você queria). Se você não quiser mostrar as salas depois que elas forem excluídas, você deve bloquear as linhas comSELECT FOR UPDATE
-
EmInnoDB,REPEATABLE READeSERIALIZABLEsão coisas diferentes:leitores emSERIALIZABLEmode define bloqueios de próxima tecla nos registros que eles avaliam, impedindo efetivamente oDMLsimultâneo neles. Portanto, você não precisa de umSELECT FOR UPDATEno modo serializável, mas precisa deles emREPEATABLE READouREAD COMMITED.
Observe que o padrão nos modos de isolamento determina que você não veja certas peculiaridades em suas consultas, mas não define como (com bloqueio ou com
MVCC ou então). Quando eu digo "você não precisa de
SELECT FOR UPDATE " Eu realmente deveria ter adicionado "por causa dos efeitos colaterais da implementação de determinados mecanismos de banco de dados".