sql >> Base de Datos >  >> RDS >> Mysql

Insertar una fila y evitar la condición de carrera (PHP/MySQL)

Por lo general, la solución a tales problemas de concurrencia involucra transacciones y bloqueo optimista. :cuando actualice el contador, agregue un where cláusula para comprobar el valor antiguo y contar el número de filas actualizadas.

v = select value from counter where id=x.
update counter set value = v+1 where value = v and id=x

Si el contador se actualizó mientras tanto, la actualización no cambiará ninguna fila, por lo que sabe que debe retroceder e intentar una vez más la transacción.

Un problema es que podría conducir a una alta contención , con solo unas pocas transacciones que tienen éxito y muchas que fallan.

Entonces podría ser mejor ceñirse al bloqueo pesimista , donde primero bloquea la fila y luego la actualiza. Pero solo un punto de referencia te lo dirá.

EDITAR

Si usa la transacción sin bloqueo optimista, podría ocurrir el siguiente escenario.

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 transacciones tienen éxito, el valor es 50, pero hay una inconsistencia.