Una lectura con bloqueo, un UPDATE
, o un
DELETE
generalmente establecen bloqueos sobre
cada registro de índice que es examinado durante el
procesamiento de la consulta SQL. No importa si en la consulta
hay condiciones WHERE
que excluirían la
fila, InnoDB
no recuerda exactamente la
condición WHERE
, solamente los rangos de
índices que fueron examinados. Los bloqueos sobre los registros
son normalmente bloqueos de próxima clave, que también impiden
las inserciones en las posiciones vacías (“gap”)
inmediatamente anteriores a los registros.
Si los bloqueos a establecer son exclusivos, entonces
InnoDB
recupera también los registros de
índices agrupados (clustered) y los bloquea.
Si no hay índices apropiados para la consulta y MySQL debe examinar la tabla entera para procesarla, se bloqueará cada fila en la tabla, lo que impide cualquier inserción de otros usuarios. Es importante crear índices adecuados de modo que las consultas no examinen muchas filas innecesariamente.
SELECT ... FROM
es una lectura
consistente, que lee una captura de la base de datos y no
establece bloqueos a menos que el nivel de aislamiento de la
transacción sea SERIALIZABLE
. Para el
nivel SERIALIZABLE
, se establecen
bloqueos compartidos de próxima clave en los registros de
índice encontrados.
SELECT ... FROM ... LOCK IN SHARE MODE
establece bloqueos compartidos de próxima clave en todos
los registros de índice hallados por la lectura.
SELECT ... FROM ... FOR UPDATE
establece
bloqueos exclusivos de próxima clave en todos los registros
de índice hallados por la lectura.
INSERT INTO ... VALUES (...)
establece un
bloqueo exclusivo sobre la fila insertada. Nótese que no se
trata de un bloqueo de próxima clave, y no evita que otros
usuarios inserten registros en la posición vacía
precedente. Si ocurriese un error por duplicación de
claves, se establecerá un bloqueo compartido sobre el
registro de índice duplicado.
Mientras se inicializa una columna previamente declarada
AUTO_INCREMENT
, InnoDB
establece un bloqueo exclusivo al final del índice asociado
con dicha columna. Al accederse al contador de
autoincremento, InnoDB
emplea una modo de
bloqueo de tabla específico llamado
AUTO-INC
, que dura solamente hasta el
final de la actual consulta SQL, en lugar de existir hasta
el final de la transacción. Consulte
Sección 15.10.2, “InnoDB
y AUTOCOMMIT
”.
En MySQL 5.0, InnoDB
trae el valor de una
columna previamente declarada
AUTO_INCREMENT
sin establecer ningún
bloqueo.
INSERT INTO T SELECT ... FROM S WHERE ...
establece un bloqueo exclusivo (pero no de próxima clave)
en cada fila insertada dentro de T
. La
búsqueda en S
se hace como una lectura
consistente, pero se establecen bloqueos compartidos de
próxima clave en S
si está activado el
registro binario (binary logging) de MySQL.
InnoDB
tiene que establecer bloqueos en
este último caso: en una recuperación de tipo roll-forward
desde una copia de respaldo, cada semtencia SQL debe ser
ejecutada en exactamente la misma manera en que se hizo
originalmente.
CREATE TABLE ... SELECT ...
lleva a cabo
el SELECT
como una lectura consistente o
con bloqueos compartidos, como en el punto anterior.
REPLACE
se ejecuta del mismo modo que una
inserción si no hay colisiones con claves únicas. En otro
caso, se coloca un bloqueo exclusivo de próxima clave en la
fila que será actualizada.
UPDATE ... WHERE ...
establece un bloqueo
exclusivo de próxima clave sobre cada registro encontrado
por la búsqueda.
DELETE FROM ... WHERE ...
establece un
bloqueo exclusivo de próxima clave sobre cada registro
encontrado por la búsqueda.
Si se define una restricción FOREIGN KEY
sobre una tabla, cualquier inserción, actualización o
eliminación que necesite la verificación de las
condiciones impuestas por la restricción establecerá
bloqueos compartidos a nivel de registro sobre los registros
examinados durante la verificación.
InnoDB
también establece estos bloqueos
en el caso de que la verificación falle.
LOCK TABLES
establece bloqueos de tabla,
pero es la capa de MySQL de mayor nivel por debajo de la
capa de InnoDB
la que establece estos
bloqueos. InnoDB
tiene conocimiento de
los bloqueos de tabla si se establecen
innodb_table_locks=1
y
AUTOCOMMIT=0
, y la capa de MySQL por
debajo de InnoDB
sabe acerca de los
bloqueos a nivel de fila. En otro caso, la detección
automática de deadlocks de InnoDB no puede detectar los
deadlocks donde estén involucradas estas tablas. Además,
puesto que la capa superior de MySQL no sabe acerca de
bloqueos a nivel de fila, es posible obtener un bloqueo de
tabla sobre una tabla donde otro usuario ha colocado
bloqueos a nivel de fila. Sin embargo, esto no pone en
peligro la integridad de la transacción, como se dice en
Sección 15.10.10, “Detección de interbloqueos (deadlocks) y cancelación de transacciones
(rollbacks)”. Consulte
también Sección 15.16, “Restricciones de las tablas InnoDB
”.
É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.