Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Quando usar SELECT ... FOR UPDATE?


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 deve SELECT id FROM rooms FOR UPDATE , evitando assim que o Thread 2 seja excluído de rooms 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 em MySQL (e vários outros sistemas antigos) bloqueia toda a tabela durante uma consulta.

  • Em SQL Server , SELECT consultas colocam bloqueios compartilhados nos registros/páginas/tabelas que examinaram, enquanto DML 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 ou DELETE A consulta será bloqueada até que outra sessão seja confirmada.

  • Em bancos de dados que usam MVCC (como Oracle , PostgreSQL , MySQL com InnoDB ), um DML 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, um SELECT FOR UPDATE seria útil:bloquearia SELECT ou o DELETE consulta até que outra sessão seja confirmada, assim como SQL Server faz.

Quando se deve usar REPEATABLE_READ isolamento de transação versus READ_COMMITTED com SELECT ... 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)

  • Em Oracle e anterior PostgreSQL versões, REPEATABLE READ é na verdade um sinônimo para SERIALIZABLE . Basicamente, isso significa que a transação não vê as alterações feitas após o início. Portanto, nesta configuração, o último Thread 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 com SELECT FOR UPDATE

  • Em InnoDB , REPEATABLE READ e SERIALIZABLE são coisas diferentes:leitores em SERIALIZABLE mode define bloqueios de próxima tecla nos registros que eles avaliam, impedindo efetivamente o DML simultâneo neles. Portanto, você não precisa de um SELECT FOR UPDATE no modo serializável, mas precisa deles em REPEATABLE READ ou READ 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".