Granularidad de los bloqueos de MySQL

1. Bloquear granularidad

Los bloqueos que mencionamos anteriormente son todos para registros, y también pueden llamarse bloqueos de nivel de fila o bloqueos de fila. Bloquear un registro solo afecta a este registro. Decimos que la granularidad de este bloqueo es relativamente buena; de hecho, una transacción también puede ser bloqueado en el nivel de la tabla, que naturalmente se denomina bloqueo de nivel de tabla o bloqueo de tabla. El bloqueo de una tabla afecta a los registros de toda la tabla. Decimos que la granularidad del bloqueo es relativamente gruesa. Los bloqueos agregados a la tabla también se pueden dividir en bloqueos compartidos (bloqueos S) y bloqueos exclusivos (bloqueos X)

1.1, comparación de bloqueos de tabla y bloqueos de fila

Granularidad de bloqueo: bloqueo de tabla > bloqueo de fila

Eficiencia de bloqueo: bloqueo de mesa> bloqueo de fila

Probabilidad de conflicto: bloqueo de tabla > bloqueo de fila

Rendimiento de concurrencia: bloqueo de tabla < bloqueo de fila

1.2, agregue S lock a la tabla

Si una transacción agrega un bloqueo S a la tabla, entonces:

Otras transacciones pueden continuar para obtener el bloqueo S de la tabla

Otras transacciones pueden continuar obteniendo bloqueos S para ciertos registros en la tabla

Otras transacciones no pueden continuar obteniendo el bloqueo X de la tabla

Otras transacciones no pueden continuar obteniendo bloqueos X para ciertos registros en la tabla

1.3, agregue bloqueo X a la tabla

Si una transacción agrega un bloqueo X a la tabla (lo que significa que la transacción quiere monopolizar la tabla), entonces:

Otras transacciones no pueden continuar obteniendo el bloqueo S de la tabla

Otras transacciones no pueden continuar obteniendo bloqueos S para ciertos registros en la tabla

Otras transacciones no pueden continuar obteniendo el bloqueo X de la tabla

Otras transacciones no pueden continuar obteniendo bloqueos X en ciertos registros de la tabla.

Para comprender mejor los bloqueos S y X en el nivel de la mesa y los bloqueos de intención detrás, tomemos un ejemplo de la vida real. Usamos el otrora popular proyecto de Internet Shared Office para ilustrar el bloqueo:

Shared Office tiene un edificio, y el edificio naturalmente tiene muchos pisos. Las oficinas son todas compartidas y los clientes pueden elegir cualquier oficina para trabajar. Cada piso puede acomodar a los clientes para trabajar al mismo tiempo. Cada vez que un cliente ingresa a la oficina, es equivalente a colgar un candado S en la entrada de cada piso. Si muchos clientes ingresan a la oficina, es equivalente a colgar un montón de S cerraduras en la entrada de cada piso Cerraduras (similares a las cerraduras S a nivel de fila).

En ocasiones se realizarán trabajos de mantenimiento en el suelo, como cambiar el suelo, cambiar el techo, comprobar el agua y la electricidad, etc. Estos mantenimientos no se pueden realizar al mismo tiempo. Si se reacondiciona el piso para un determinado proyecto, no se permite que los clientes vengan a trabajar y no se permiten otros proyectos de mantenimiento. En este momento, es equivalente a colgar un candado X (similar a un candado X a nivel de fila) en la puerta del piso.

Las dos cerraduras mencionadas anteriormente son para pisos, pero a veces tenemos algunas necesidades especiales:

R. Hay inversores que quieren inspeccionar el entorno de Office.

Los inversores y las empresas no quieren afectar el acceso de los clientes al trabajo, pero no hay pisos para mantenimiento en este momento, por lo que se puede colocar una cerradura S (similar a una cerradura S a nivel de mesa) en la puerta del edificio. en este momento:

Los clientes que vienen a trabajar pueden continuar ingresando al edificio para trabajar después de ver la cerradura S en la puerta del edificio.

Cuando el reparador ve la cerradura S en la entrada del edificio, primero espera en la entrada del edificio. Cuando el inversor se va, quita la cerradura S del edificio y luego ingresa al edificio para mantenimiento.

B. La empresa necesita negociar los términos con el arrendador.

Los pisos de trabajo no están permitidos en el edificio en este momento, y no se permite el mantenimiento del piso. Por lo tanto, puede colocar un candado X (similar a un candado X a nivel de mesa) en la entrada del edificio. en este momento:

Los clientes que vienen a trabajar ven que hay un candado X en la entrada del edificio, por lo que deben esperar en la entrada del edificio. Cuando se negocian las condiciones, retire el candado X del edificio y luego ingrese al edificio para trabajar.

Cuando el reparador ve la cerradura X en la entrada del edificio, primero espera en la entrada del edificio. Cuando termina la negociación, quita la cerradura X del edificio y luego ingresa al edificio para mantenimiento.

2. Bloqueo de intención

Pero hay dos problemas en el ejemplo anterior:

Si queremos bloquear el edificio como un todo, primero debemos asegurarnos de que no haya pisos en mantenimiento en el edificio. Si hay pisos en mantenimiento, debemos esperar hasta que se complete el mantenimiento antes de poder cerrar el edificio como entero.

Si queremos bloquear el edificio como un todo, primero debemos asegurarnos de que no haya pisos de oficinas ni pisos en mantenimiento en el edificio. Si hay pisos de oficinas o pisos en mantenimiento, debemos esperar hasta que todos los estudiantes de oficina salir de sus oficinas y trabajadores de mantenimiento La cerradura X en el edificio en su conjunto solo se puede cerrar después de que el piso se repara y se deja.

Cuando bloqueamos el edificio como un todo (bloqueo de mesa), ¿cómo sabemos si algún piso del edificio ha sido bloqueado (bloqueo de fila)? ¿Verificar a su vez si la puerta de cada piso está cerrada? ¡Entonces esta eficiencia es demasiado lenta! Entonces InnoDB propuso un bloqueo de intención (nombre en inglés: Intention Locks):

Intention Shared Lock , nombre en inglés: Intention Shared Lock, bloqueo IS para abreviar. Cuando una transacción está a punto de agregar un bloqueo S en un registro, primero debe agregar un bloqueo IS en el nivel de la tabla.

Intention Exclusive Lock , nombre en inglés: Intention Exclusive Lock, denominado bloqueo IX. Cuando una transacción va a agregar un bloqueo X a un registro, primero debe agregar un bloqueo IX en el nivel de la tabla.

La perspectiva vuelve al edificio y al suelo:

Si un cliente va a trabajar en un piso, primero coloca una cerradura IS (cerradura a nivel de mesa) en la puerta de todo el edificio y luego coloca una cerradura S (cerradura de fila) en la puerta del piso.

Si un trabajador de mantenimiento va al piso para el mantenimiento, primero coloca una cerradura IX (cerradura a nivel de mesa) en la puerta de todo el edificio y luego coloca una cerradura X (cerradura de fila) en la puerta del piso.

después:

Si un inversor quiere visitar el edificio, es decir, cuando quiere poner una cerradura S (cerradura de mesa) frente a la entrada del edificio, primero debe verificar si hay una cerradura IX en la entrada del edificio. La cerradura solo se puede agregar a todo el edificio después de quitar la cerradura IX.

Si hay una condición para ocupar el edificio, es decir, cuando desea colocar una cerradura X (cerradura de mesa) frente a la puerta del edificio, primero debe verificar si hay una cerradura IS o una cerradura IX en la puerta del edificio. edificio.Si hay, significa que hay pisos para oficinas o mantenimiento.La cerradura X solo se puede agregar a todo el edificio después de que los clientes hayan terminado su trabajo y mantenimiento y hayan quitado la cerradura IS y la cerradura IX.

Nota: Cuando el cliente agrega una cerradura IS a la puerta del edificio, no le importa si hay una cerradura IX en la puerta del edificio. Cuando el trabajador de mantenimiento agrega una cerradura IX a la puerta del edificio, no le importa No importa si hay una cerradura IS u otras cerraduras IX en la puerta del edificio. Los bloqueos IS y IX solo se utilizan para determinar si hay pisos ocupados en el edificio en el momento actual, es decir, se utilizarán al agregar bloqueos S o bloqueos X al edificio.

En resumen : los bloqueos IS e IX son bloqueos a nivel de tabla. Solo se proponen para determinar rápidamente si los registros en la tabla están bloqueados al agregar bloqueos S y bloqueos X a nivel de tabla más adelante, para evitar ver la tabla por recorrido. No hay registros bloqueados en . Es decir, las cerraduras IS y las cerraduras IX son compatibles, y las cerraduras IX y las cerraduras IX son compatibles. Dibujemos una tabla para ver la compatibilidad de varios bloqueos a nivel de tabla :

compatibilidad X IX S ES
X incompatible incompatible incompatible incompatible
IX incompatible incompatible
S incompatible incompatible
ES incompatible

Combinación de bloqueos: ( los bloqueos de intención no tienen bloqueos de fila )

combinación X IX S ES
bloqueo de mesa tener tener tener tener
bloqueo de fila tener tener

3. Bloqueos de filas y bloqueos de tablas en MySQL

MySQL admite múltiples motores de almacenamiento y diferentes motores de almacenamiento admiten bloqueos de manera diferente. Por supuesto, nuestro enfoque sigue estando en los bloqueos del motor de almacenamiento InnoDB, y otros motores de almacenamiento solo echan un vistazo.

3.1, bloqueos en otros motores de almacenamiento

Los motores de almacenamiento, como MyISAM, MEMORY y MERGE, solo admiten bloqueos de nivel de tabla y estos motores no admiten transacciones, por lo que los bloqueos que utilizan estos motores de almacenamiento generalmente son para la sesión actual. Por ejemplo, realizar una operación SELECCIONAR en una tabla en la Sesión 1 es equivalente a agregar un bloqueo S de nivel de tabla a la tabla.Si la operación SELECCIONAR no se completa, realizar una operación ACTUALIZAR en la tabla en la Sesión 2 es equivalente a obtener El Bloqueo X de la tabla, esta operación se bloqueará hasta que se complete la operación SELECCIONAR en la Sesión 1, después de que se libere el bloqueo S a nivel de tabla, la operación ACTUALIZAR en la tabla en la Sesión 2 puede continuar para obtener el bloqueo X, y luego ejecutar la declaración de actualización específica.

Debido a que las tablas que utilizan motores de almacenamiento como MyISAM, MEMORY y MERGE solo permiten que una sesión escriba en la tabla al mismo tiempo, estos motores de almacenamiento se utilizan mejor para operaciones de solo lectura o principalmente de lectura o escenario de un solo usuario. Además, hay una función llamada Inserciones simultáneas en el motor de almacenamiento MyISAM, que admite la inserción simultánea de registros al leer tablas MyISAM, lo que puede mejorar algunas velocidades de inserción. Para obtener más detalles sobre las inserciones simultáneas, consulte la documentación.

3.2, bloqueos en el motor de almacenamiento InnoDB

El motor de almacenamiento InnoDB admite bloqueos de tablas y bloqueos de filas. Los bloqueos de tabla son simples de implementar y ocupan menos recursos, pero la granularidad es muy gruesa. A veces, solo necesita bloquear algunos registros, pero usar bloqueos de tabla equivale a bloquear todos los registros de la tabla, por lo que el rendimiento es relativamente bajo. La granularidad de los bloqueos de fila es más fina, lo que permite un control de concurrencia más preciso. Echemos un vistazo más de cerca a continuación.

3.2.1, bloqueos a nivel de tabla en InnoDB

3.2.1.1, bloqueos S a nivel de tabla, bloqueos X y bloqueos de metadatos

Al ejecutar instrucciones SELECT, INSERT, DELETE y UPDATE en una tabla, el motor de almacenamiento de InnoDB no agregará bloqueos S o bloqueos X a nivel de tabla a la tabla.

Además, cuando se ejecutan en una tabla algunas declaraciones DDL como ALTER TABLE y DROP TABLE, otras transacciones bloquearán la ejecución simultánea de declaraciones como SELECT, INSERT, DELETE y UPDATE en esta tabla. Las declaraciones SELECT, INSERT, DELETE y UPDATE en una tabla, la ejecución de declaraciones DDL en esta tabla en otras sesiones también se bloqueará. Este proceso en realidad se implementa mediante el llamado bloqueo de metadatos (nombre en inglés: Metadata Locks, MDL para abreviar) en la capa del servidor. En general, los bloqueos S a nivel de tabla y los bloqueos proporcionados por el propio motor de almacenamiento InnoDB no serán Usado Bloqueo X.

De hecho, el bloqueo S o X de nivel de tabla proporcionado por el motor de almacenamiento InnoDB es bastante insípido y solo se utilizará en algunos casos especiales, como durante la recuperación de fallas. Sin embargo, todavía podemos obtenerlo manualmente, por ejemplo, cuando la variable de sistema autocommit=0 e innodb_table_locks=1, obtener manualmente el bloqueo S o el bloqueo X de la tabla t proporcionado por el motor de almacenamiento InnoDB se puede escribir de la siguiente manera:

LOCK TABLES t READ: el motor de almacenamiento InnoDB agrega un bloqueo S de nivel de tabla a la tabla t.

LOCK TABLES t WRITE: el motor de almacenamiento InnoDB agrega un bloqueo X de nivel de tabla a la tabla t.

Intente evitar el uso de declaraciones de tabla de bloqueo manual, como LOCK TABLES, en tablas que usan el motor de almacenamiento InnoDB. No brindan ninguna protección adicional, solo reducen la capacidad de concurrencia.

3.2.1.2, bloqueos IS y bloqueos IX a nivel de tabla

Antes de agregar bloqueos S a algunos registros de tablas usando el motor de almacenamiento InnoDB, necesitamos agregar un bloqueo IS a nivel de tabla Antes de agregar bloqueos X a algunos registros de tablas usando el motor de almacenamiento InnoDB, entonces necesita agregar un Bloqueo IX en el nivel de la mesa primero.

La misión de los bloqueos IS y los bloqueos IX es solo determinar si hay registros bloqueados en la tabla al agregar bloqueos S y bloqueos X a nivel de tabla, para evitar usar el recorrido para verificar si hay registros bloqueados en la tabla. No podemos agregar bloqueos de intención manualmente, solo el motor de almacenamiento InnoDB puede agregarlos por sí mismo.

3.2.1.3, bloqueo AUTO-INC a nivel de mesa

En el proceso de usar MySQL, podemos agregar el atributo AUTO_INCREMENT a cierta columna de la tabla, y luego, al insertar registros, es posible que no se especifique el valor de la columna, y el sistema le asignará automáticamente un valor incremental. el sistema realiza esta modificación automática de AUTO_INCREMENT Hay dos principios principales de asignación de columna incremental:

1. Adopte el bloqueo AUTO-INC, es decir, agregue un bloqueo AUTO-INC en el nivel de la tabla al ejecutar la declaración de inserción, y luego asigne un valor incremental a la columna modificada AUTO_INCREMENT de cada registro que se insertará. , Luego suelte el bloqueo AUTO-INC. Cuando una transacción de este tipo mantiene el bloqueo AUTO-INC, las declaraciones de inserción de otras transacciones se bloquearán, lo que puede garantizar que el valor incremental asignado en una declaración sea continuo.

Si nuestra declaración de inserción no puede determinar cuántos registros insertar antes de la ejecución (es imposible predecir la cantidad de registros que se insertarán), por ejemplo, usando declaraciones de inserción como INSERTAR... SELECCIONAR, REEMPLAZAR... SELECCIONAR o CARGAR DATOS , generalmente es usar el bloqueo AUTO-INC para generar el valor correspondiente a la columna modificada por AUTO_INCREMENT.

2. Use un bloqueo ligero para obtener el bloqueo ligero al generar el valor de la columna modificada AUTO_INCREMENT para la declaración de inserción, y luego genere el valor de la columna AUTO_INCREMENT que se requiere para esta declaración de inserción, y luego coloque el bloqueo ligero La magnitud se libera el bloqueo, y no es necesario liberar el bloqueo hasta que se ejecute la instrucción de inserción completa.

Si nuestra declaración de inserción puede determinar cuántos registros insertar antes de la ejecución, por ejemplo, en el ejemplo sobre la tabla t que mencionamos anteriormente, podemos determinar insertar 2 registros antes de que se ejecute la declaración, entonces generalmente usar valores ligeros Asignar valores a las columnas modificado por AUTO_INCREMENT en forma de bloqueos. Este método puede evitar bloquear la mesa y mejorar el rendimiento de la inserción.

InnoDB proporciona una variable de sistema llamada innodb_autoinc_lock_mode para controlar cuál de los dos métodos anteriores se usa para asignar valores a las columnas modificadas por AUTO_INCREMENT, cuando el valor de innodb_autoinc_lock_mode es 0, se usa el bloqueo AUTO-INC, cuando el valor de innodb_autoinc_lock_mode es Cuando 2, siempre se utilizan bloqueos ligeros; cuando el valor de innodb_autoinc_lock_mode es 1, los dos métodos se mezclan (es decir, los bloqueos ligeros se utilizan cuando se determina el número de registros insertados y los bloqueos AUTO-INC se utilizan cuando incierto).

Sin embargo, cuando el valor de innodb_autoinc_lock_mode es 2, puede causar que se crucen los valores generados por las declaraciones de inserción en diferentes transacciones para las columnas modificadas por AUTO_INCREMENT, lo que no es seguro en el escenario de replicación maestro-esclavo.

mostrar variables como 'innodb_autoinc_lock_mode';

El valor predeterminado es 1 en MySQL5.7.X.

3.2.2, bloqueos de nivel de fila en InnoDB

Los bloqueos de fila, también conocidos como bloqueos de registros, como su nombre indica, son bloqueos que se agregan a los registros. Pero debe tenerse en cuenta que este registro se refiere a bloquear los elementos del índice en el índice. La función de implementación de bloqueo de fila de InnoDB significa que InnoDB usa bloqueos de nivel de fila solo cuando los datos se recuperan a través de condiciones de índice; de ​​lo contrario, InnoDB usa bloqueos de tabla.

Ya sea que use índices de clave principal, índices únicos o índices ordinarios, InnoDB usa bloqueos de fila para bloquear datos.

Los bloqueos de fila solo se pueden usar si el plan de ejecución realmente usa el índice: incluso si el campo de índice se usa en la condición, MySQL determina si usar el índice para recuperar datos al juzgar el costo de los diferentes planes de ejecución. que el escaneo completo de la tabla es eficiente Superior, por ejemplo, para algunas tablas muy pequeñas, no usará índices En este caso, InnoDB usará bloqueos de tabla en lugar de bloqueos de fila.

Al mismo tiempo, cuando usamos condiciones de rango en lugar de condiciones de igualdad para recuperar datos y solicitar bloqueos, InnoDB bloqueará los elementos de índice de los registros de datos existentes que cumplan con las condiciones.

Pero incluso para los bloqueos de fila, InnoDB se divide en varios tipos. En otras palabras, incluso si se agregan bloqueos de fila al mismo registro, si los tipos son diferentes, los efectos serán diferentes. Usamos el maestro anterior, agregamos un índice e insertamos algunos registros.

ÍNDICE `idx_number`(`número`)

Echemos un vistazo a los tipos de bloqueo de fila más utilizados.

Registro de bloqueos

También se le llama bloqueo de registro, que consiste en bloquear solo un registro.El nombre oficial del tipo es: LOCK_REC_NOT_GAP. Por ejemplo, el diagrama esquemático de agregar un bloqueo de registro al registro con un valor numérico de 6 es el siguiente:

Los bloqueos de registro se dividen en bloqueos S y bloqueos X. Cuando una transacción adquiere un bloqueo de registro tipo S para un registro, otras transacciones pueden continuar adquiriendo el bloqueo de registro tipo S para el registro, pero no pueden continuar adquiriendo el tipo X. bloqueo de registro. ;Cuando una transacción adquiere un bloqueo de registro de tipo X para un registro, otras transacciones no pueden continuar adquiriendo el bloqueo de registro de tipo S ni el bloqueo de registro de tipo X para el registro;

Bloqueos de brecha

Decimos que MySQL puede resolver el problema de la lectura fantasma bajo el nivel de aislamiento REPEATABLE READ.Hay dos soluciones, que pueden resolverse usando el esquema MVCC o usando el esquema de bloqueo. Pero hay un problema al usar la solución de bloqueo, es decir, cuando la transacción ejecuta la operación de lectura por primera vez, esos registros fantasma aún no existen y no podemos agregar bloqueos de registro a estos registros fantasma. InnoDB propone un bloqueo llamado Gap Locks. El nombre oficial del tipo es: LOCK_GAP. También podemos llamarlo gap lock para abreviar.

El bloqueo de brecha es esencialmente para bloquear la brecha antes y después del índice, no para bloquear el índice en sí.

La sesión 1 inicia una transacción y ejecuta

comenzar; 
actualice el dominio del conjunto de maestros = 'JVM' donde número = '6';

Habrá bloqueos entre 2~6 y 6~10.

Como se muestra en la figura, los bloqueos de espacio se agregan a los registros 2~6 y 6~10, lo que significa que otras transacciones no pueden insertar nuevos registros en el espacio antes y después de este registro.

comenzar; 
insertar en el valor del maestro (7, '晁', 'docker');

¿Por qué no se puede insertar? Porque si se va a insertar el registro (7, 'chao', 'docker'), el índice idx_number solo cae entre 6 y 10, que está bloqueado y, por supuesto, no se permite la inserción.

Pero cuando la declaración SQL se convierte en: insertar en el valor del maestro (70, 'Chao', 'docker'); ¿se puede insertar?

Por supuesto que puede, porque el registro 70 no está en el rango bloqueado.

Supongo que te gusta

Origin blog.csdn.net/m0_70299172/article/details/130478891
Recomendado
Clasificación