En el bloqueo a nivel de fila, InnoDB
utiliza
un algoritmo llamado bloqueo de próxima
clave. InnoDB
lleva a cabo el
bloqueo a nivel de fila de tal manera que cuando busca o recorre
el índice de una tabla, establece bloqueos compartidos o
exclusivos en los registros de índice que encuentra. Por lo
tanto, los bloqueos a nivel de fila son en realidad bloqueos
sobre registros del índice.
El conjunto de bloqueos de InnoDB
sobre los
registros del índice también afecta al “gap”
(posición vacía) que precede al registro de índice. Si un
usuario tiene un bloqueo compartido o exclusivo sobre un
registro R
en un índice, otro usuario no
puede insertar un nuevo registro inmediatamente antes de
R
en el orden del índice. Este bloqueo de
posiciones vacías se hace para evitar el llamado
“problema fantasma”. Suponiendo que se desean leer
y bloquear todos los hijos de la tabla hijos
que tengan un identificador mayor a 100, con el posterior
intento de actualizar algunas columnas en las filas
seleccionadas:
SELECT * FROM child WHERE id > 100 FOR UPDATE;
Suponiendo que hay un índice sobre la columna
id
, la consulta recorre ese índice
comenzando por el primer registro donde id
es
mayor a 100. Si el bloqueo establecido sobre el índice no
bloqueara también las inserciones hechas en las posiciones
vacías, durante el proceso se podría insertar una nueva fila
en la tabla. Si se ejecuta la misma sentencia
SELECT
dentro de la misma transacción, se
podría ver una nueva fila en el conjunto de resultados devuelto
por la consulta. Esto es contrario al principio de aislamiento
de las transacciones: una transacción deberia ejecutarse de
forma que los datos que ha leido no cambien en el transcurso de
la misma. Si se considera un conjunto de columnas como datos, el
nuevo registro hijo “fantasma” violaría el
principio de aislamiento.
Cuando InnoDB
recorre un índice, también
puede bloquear la posición vacía después del último registro
del índice. Es precisamente lo que ocurre en el ejemplo
anterior: Los bloqueos impuestos por InnoDB
evitan cualquier inserción en la tabla donde
id
fuera mayor de 100.
Se puede emplear bloqueo de próxima clave para efectuar el control de la unicidad en una aplicación: Si se leen los datos en modo compartido y no se ve un duplicado de la fila que se va a insertar, entonces puede hacerse con la seguridad de que el bloqueo de próxima clave establecido sobre el registro que continúa a la fila insertada evita que cualquiera inserte un duplicado de ésta. Por lo tanto, el bloqueo de próxima clave permite “bloquear” la no existencia de algo en la tabla.
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.