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

Como faço para bloquear uma linha do InnoDB que ainda não existe?


Embora a resposta acima seja verdadeira, pois um SELECT ... FOR UPDATE impedirá que sessões / transações simultâneas insiram o mesmo registro, isso não é a verdade completa. Atualmente estou lutando com o mesmo problema e cheguei à conclusão de que o SELECT ... FOR UPDATE é quase inútil nessa situação pelo seguinte motivo:

Uma transação / sessão simultânea também pode fazer um SELECT ... FOR UPDATE no mesmo valor de registro / índice, e o MySQL aceitará isso imediatamente (sem bloqueio) e sem gerar erros. Claro, assim que a outra sessão fizer isso, sua sessão também não poderá mais inserir o registro. Nem a sua nem a outra sessão/transação obtêm qualquer informação sobre a situação e pensam que podem inserir o registro com segurança até que realmente tentem fazê-lo. Tentar inserir leva a um impasse ou a um erro de chave duplicada, dependendo das circunstâncias.

Em outras palavras, SELECT ... FOR UPDATE impede que outras sessões insiram o(s) respectivo(s) registro(s), MAS mesmo se você fizer um SELECT ... FOR UPDATE e o respectivo registro não for encontrado, é provável que você não consiga insira esse registro. IMHO, que torna o método "first query, then insert" inútil.

A causa do problema é que o MySQL não oferece nenhum método para realmente bloquear registros inexistentes. Duas sessões / transações simultâneas podem bloquear registros inexistentes "FOR UPDATE" ao mesmo tempo, algo que realmente não deveria ser possível e que torna o desenvolvimento significativamente mais difícil.

A única maneira de contornar isso parece ser usando tabelas de semáforos ou bloqueando a tabela inteira ao inserir. Por favor, consulte a documentação do MySQL para referência adicional sobre como bloquear tabelas inteiras ou usar tabelas de semáforos.

Apenas meus 2 centavos...