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

Insira uma linha e evite a condição de corrida (PHP/MySQL)


Normalmente, a solução para esses problemas de simultaneidade envolve transações e bloqueio otimista :quando você atualizar o contador, adicione um where cláusula para verificar o valor antigo e contar o número de linhas atualizadas.
v = select value from counter where id=x.
update counter set value = v+1 where value = v and id=x

Se o contador foi atualizado nesse meio tempo, a atualização não alterará nenhuma linha, então você sabe que precisa reverter e tentar mais uma vez a transação.

Um problema é que isso pode levar a uma alta contenção , com apenas algumas transações bem-sucedidas e muitas falhas.

Então pode ser melhor manter o bloqueio pessimista , onde você bloqueia a linha primeiro e depois a atualiza. Mas apenas um benchmark lhe dirá.

EDITAR

Se você usar transação sem bloqueio otimista, o cenário a seguir pode acontecer.
Max authorized = 50. Current value = 49.

T1: start tx, read value --> 49
T2: start tx, read value --> 49
T1: update value --> 50, acquire a row lock
T1: commits --> release the lock
T2: update value --> 50, acquire a row lock
T2: commits --> release the lock

Ambas as transações são bem-sucedidas, o valor é 50, mas há uma inconsistência.