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

Bloqueo de nivel de fila en Mysql

En lugar de FOR UPDATE use LOCK IN SHARE MODE . FOR UPDATE evita que otras transacciones también lean la fila. LOCK IN SHARE MODE permite la lectura, pero impide la actualización.

Referencia:Manual de MySQL

------ sesión 1

START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;

----- sesión 2 (que ya no está bloqueada :) )

START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;

Actualización:

Darse cuenta de que la tabla no tiene índice en t , tengo la siguiente explicación:

Primero, la transacción T1 bloquea la fila 1 en SELECT * FROM test WHERE t=1 FOR UPDATE

A continuación, la transacción T2 intenta ejecutar UPDATE test SET NAME='irfandd' WHERE t=4 . Para averiguar qué filas están afectadas, debe escanear todas las filas, incluida la fila 1 . Pero eso está bloqueado, por lo que T2 debe esperar hasta que finalice T1. Si hay algún tipo de índice, WHERE t=4 puede usar el índice para decidir si fila 1 contiene t=4 o no, así que no hay necesidad de esperar.

Opción 1: agregue un índice en test.t para que su actualización pueda usarlo.

Opción 2: use LOCK IN SHARE MODE , que está destinado a poner un bloqueo de lectura únicamente. Desafortunadamente, esta opción crea un punto muerto. Curiosamente, la transacción T2 se ejecuta (actualizando la fila 4) y T1 falla (actualizando la fila 2). Parece que T1 bloquea la lectura fila 4 además, y como T2 lo modifica, T1 falla por el nivel de aislamiento de la transacción (LECTURA REPETIBLE por defecto ). La solución final sería jugar con Niveles de aislamiento de transacciones , usando READ UNCOMMITTED o READ COMMITTED niveles de transacciones.

La más simple es Opción 1 , en mi humilde opinión, pero depende de tus posibilidades.