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 derooms
até que a Linha 1 seja concluída. Isso é correto?
Isso depende do controle de simultaneidade que seu sistema de banco de dados está usando.
-
MyISAM
emMySQL
(e vários outros sistemas antigos) bloqueia toda a tabela durante uma consulta.
-
EmSQL Server
,SELECT
consultas colocam bloqueios compartilhados nos registros/páginas/tabelas que examinaram, enquantoDML
consultas 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,SELECT
ouDELETE
A consulta será bloqueada até que outra sessão seja confirmada.
-
Em bancos de dados que usamMVCC
(comoOracle
,PostgreSQL
,MySQL
comInnoDB
), umDML
query 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 UPDATE
seria útil:bloqueariaSELECT
ou oDELETE
consulta até que outra sessão seja confirmada, assim comoSQL Server
faz.
Quando se deve usarREPEATABLE_READ
isolamento de transação versusREAD_COMMITTED
comSELECT ... 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) -
EmOracle
e anteriorPostgreSQL
versõ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 1
query 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 READ
eSERIALIZABLE
são coisas diferentes:leitores emSERIALIZABLE
mode define bloqueios de próxima tecla nos registros que eles avaliam, impedindo efetivamente oDML
simultâneo neles. Portanto, você não precisa de umSELECT FOR UPDATE
no modo serializável, mas precisa deles emREPEATABLE READ
ouREAD 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".