Isso surgiu a partir dessa pergunta relacionada , em que eu queria saber como forçar duas transações a ocorrerem seqüencialmente em um caso trivial (onde ambas estão operando em apenas uma única linha). Eu recebi uma resposta - use SELECT ... FOR UPDATE
como a primeira linha de ambas as transações - mas isso leva a um problema: se a primeira transação nunca for confirmada ou revertida, a segunda transação será bloqueada indefinidamente. A innodb_lock_wait_timeout
variável define o número de segundos após os quais o cliente que tenta fazer a segunda transação recebe a mensagem "Desculpe, tente novamente" ... mas, tanto quanto eu sei, eles tentariam novamente até o próximo servidor reiniciar. Então:
- Certamente deve haver uma maneira de forçar um
ROLLBACK
se uma transação estiver demorando para sempre? Devo recorrer ao uso de um daemon para eliminar essas transações? Em caso afirmativo, como seria esse daemon? - Se uma conexão é interrompida por
wait_timeout
ou nointeractive_timeout
meio da transação, a transação é revertida? Existe uma maneira de testar isso no console?
Esclarecimento : innodb_lock_wait_timeout
define o número de segundos que uma transação aguardará que um bloqueio seja liberado antes de desistir; o que eu quero é uma maneira de forçar um bloqueio a ser liberado.
Atualização 1 : Aqui está um exemplo simples que demonstra por que innodb_lock_wait_timeout
não é suficiente para garantir que a segunda transação não seja bloqueada pela primeira:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Com a configuração padrão de innodb_lock_wait_timeout = 50
, esta transação é concluída sem erros após 55 segundos. E se você adicionar um UPDATE
antes da SLEEP
linha, inicie uma segunda transação de outro cliente que tenta SELECT ... FOR UPDATE
a mesma linha, é a segunda transação que atinge o tempo limite, não a que adormeceu.
O que estou procurando é uma maneira de forçar o fim do sono repousante dessa transação.
Atualização 2 : em resposta às preocupações da hobodave sobre o quão realista é o exemplo acima, aqui está um cenário alternativo: um DBA se conecta a um servidor ativo e executa
START TRANSACTION
SELECT ... FOR UPDATE
onde a segunda linha trava uma linha na qual o aplicativo grava frequentemente. Em seguida, o DBA é interrompido e se afasta, esquecendo de finalizar a transação. O aplicativo é interrompido até a linha ser desbloqueada. Gostaria de minimizar o tempo em que o aplicativo está bloqueado como resultado desse erro.
ROLLBACK
na primeira transação, se demorar mais de n
alguns segundos para concluir. Existe alguma maneira de fazer isso?
MYSQL
não tem uma configuração para evitar esse cenário. Porque não é aceitável a interrupção do servidor devido à irresponsabilidade dos clientes. Não encontrei nenhuma dificuldade para entender sua pergunta também é tão relevante.