Eu não tentei usar a transação do MySQL antes, só quero esclarecer uma coisa.
Se dois usuários executassem uma consulta no momento exato, como o MySQL lidaria com isso? por exemplo, os usuários estão tentando atualizar um registro.
user1: atualização do conjunto da tabela coluna = coluna - 4 onde column_id = 1;
user2: atualização do conjunto da tabela coluna = coluna - 7 onde column_id = 1;
Agora, se eu usar transações, o MySQL escolherá qual consulta será executada primeiro e bloqueará o segundo usuário até que a primeira consulta seja confirmada? Isso será um bloqueio de tabela ou um bloqueio de linha?
E se um terceiro usuário emitir uma instrução select? Qual será o valor que o MySQL retornará?
PS isso será no Innodb.
Uma única instrução como essa funciona da mesma forma com MyISAM ou InnoDB, com uma transação ou com autocommit=ON. Ele bloqueia o suficiente para fazer a consulta, bloqueando assim a outra conexão. Quando terminar, a outra conexão continua. Em todos os casos, a coluna é logo decrementada em 11.
Um terceiro usuário pode ver o valor diminuído em 0 ou 4 ou 7 ou 11. O "tempo muito exato" não é realmente possível porque, em algum ponto da execução de cada instrução, um bloqueio de thread único é verificado/definido/qualquer que seja . Ou seja, eles serão serializados, tão rápido que você não poderá vê-los.
O InnoDB bloqueia apenas linhas, não tabelas. (OK, a instrução DDL faz bloqueios mais ousados.)
O que fica mais interessante é uma transação que modifica duas coisas, ou que leva um tempo considerável:
Caso de intenção: item único, mas demorando:
O select precisa ser escrito assim:
Isso diz a outras conexões "Eu pretendo atualizar a linha; por favor, não me estrague". (Eu trago este exemplo, porque muitos novatos perdem essa sutileza.)
Caso de impasse: mexendo com 2 coisas:
Este é o exemplo clássico de um impasse - cada um pega uma coisa e depois pega a outra. Claramente não pode ser feito para funcionar. Uma transação é eliminada; o outro completa. Portanto, você deve verificar se há erros, para que possa descobri-lo.
A reação normal a um deadlock é repetir toda a transação com falha. Até então, a outra conexão não estará interferindo e deve prosseguir sem problemas. (OK, outra conexão pode criar outro impasse.)
Caso de atraso: Se as duas conexões pegarem várias coisas na mesma ordem, uma poderá ser atrasada até que a outra termine. Para evitar que isso "espere para sempre", há um padrão de 50 segundos
innodb_lock_wait_timeout
. Seu par de simplesUPDATEs
é na verdade um exemplo desse caso. Um terminará prontamente; o outro está parado até que o primeiro termine.Observe como um Deadlock pode (em alguns casos) ser transformado em um Delay ao ordenar consistentemente as coisas que você toca.
autocommit=1: Com esta configuração e sem chamar
BEGIN
, cada instrução é efetivamente:autocommit=0: Este é um problema esperando para acontecer. Quando você executa uma consulta de gravação, a
BEGIN
é gerado implicitamente. No entanto, é sua responsabilidade eventualmente emitirCOMMIT
. Se você não fizer isso, você se perguntará por que seu sistema está travado. (Outro bug comum para iniciantes.) Meu conselho: "Nunca use=0
".