Anuncios

Bienvenidos sean a este post, hablaremos son un particular tipo de bloqueo.

Anuncios
Anuncios

A partir de la version 5.5 las tablas adquieren bloqueos de metadatos cuando acceden a una tabla o vista por primera vez, incluye a tablas no transaccionales como Aria, estos bloqueos previenen a las transacciones de tirar objetos bloqueados o modificar la estructura, esto es muy importante porque si una transaccion esta usando una tabla tienes que estar seguro que las columnas de la tabla o toda la tabla no desapareceran en el medio y en algunos casos los programas almacenados son tambien bloqueados, si una conexion intenta una ejecucion DDL (como una ALTER TABLE) en una tabla con el bloqueo de metadatos se retendra la conexion hasta que todos los bloqueos sean liberados, aunque estos bloqueos tienen un timeout el cual es definido por la variable lock_wait_timeout expresada en segundos.

Anuncios
Nota: 
Su valor predeterminado es 31536000 el cual equivale a un año, si este expira devuelve el error 1205.
Anuncios

A partir de la version 10.0 disponemos de un complemento llamado metadata_lock_info que nos permite ver los bloqueos de metadatos existentes, si bien es distribuido no se instala de manera predeterminada pero si lo instalamos se creara una nueva tabla llamada METADATA_LOCK_INFO en la base information_schema, esta posee las siguientes columnas:

  • THREAD_ID, almacena el id del thread que maneja el bloqueo
  • LOCK_MODE, almacena que modo esta bloqueando las operaciones
  • LOCK_DURATION, este indica si el bloqueo es valido durante la transaccion o ejecucion
  • LOCK_TYPE, almacena cual tipo de objeto es bloqueado
  • TABLE_SCHEMA, almacena el nombre de la base donde esta la tabla
  • TABLE_NAME, almacena el nombre del objeto bloqueado
Anuncios

Para poder ver los bloqueos debemos usar a SHOW PROCESSLIST, dado que cuando tiremos el comando veremos a los procesos que se estan ejecutando y las conexiones que esten esperando la liberacion de este bloqueo nos mostrara el mensaje «Waiting for table metadata lock» en la columna Extra, vamos a hacer un ejemplo para verlo en accion pero recuerden que deben instalarlo antes de hacer lo siguiente, comencemos con la creacion de una tabla:

MariaDB [test]> CREATE TABLE my_tab (a INT) ENGINE = Aria;
Anuncios

Luego iniciaremos la transaccion:

MariaDB [test]> START TRANSACTION;
Anuncios

Y nuestro siguiente paso sera agregar un nuevo valor en esta tabla:

MariaDB [test]> INSERT INTO my_tab VALUES (1);
Anuncios

Con esto realizado abramos una nueva conexion y desde esta ejecutemos el siguiente comando:

MariaDB [test]> RENAME TABLE my_tab TO tab;
Anuncios

Con este comando cambiaremos el nombre de la tabla pero si todo sale bien deberia quedar esperando a que se libere el bloqueo, para chequear nuestros bloqueos debemos abrir una tercera conexion y ejecutar el siguiente comando:

MariaDB [(none)]> SELECT * FROM information_schema.METADATA_LOCK_INFO \G
Anuncios

Esto nos devolvera la informacion sobre esta tabla, veamos un ejemplo de que puede devolvernos:

MariaDB [(none)]> SELECT * FROM information_schema.METADATA_LOCK_INFO \G
*************************** 1. row *************************** 
    THREAD_ID: 5 
    LOCK_MODE: MDL_INTENTION_EXCLUSIVE 
LOCK_DURATION: MDL_STATEMENT 
    LOCK_TYPE: Global read lock 
 TABLE_SCHEMA: 
   TABLE_NAME: 
*************************** 2. row *************************** 
    THREAD_ID: 5 
    LOCK_MODE: MDL_INTENTION_EXCLUSIVE 
LOCK_DURATION: MDL_TRANSACTION 
    LOCK_TYPE: Schema metadata lock 
 TABLE_SCHEMA: test 
   TABLE_NAME: 
*************************** 3. row *************************** 
    THREAD_ID: 4 
    LOCK_MODE: MDL_SHARED_WRITE 
LOCK_DURATION: MDL_TRANSACTION 
    LOCK_TYPE: Table metadata lock 
 TABLE_SCHEMA: test 
   TABLE_NAME: my_tab 
3 rows in set (0.12 sec) 
Anuncios

En este caso vemos que la primera conexion tiene un id de 4 y en esta el modo de bloqueo es de tipo escritura compartida en la tabla test.t, la cual presenta otras conexiones modificando la tabla, la segunda conexion tiene el id de 5 y en esta tenemos dos bloqueos que estan esperando que se libere el anterior, ahora volvamos a la primera y procedamos a finalizar el query de la transaccion pero antes de hacerlo vamos a ejecutar el siguiente query:

MariaDB [test]> SELECT * FROM t;
+------+ 
| a    | 
+------+ 
|    1 | 
+------+ 
1 row in set (0.00 sec) 
MariaDB [test]>
Anuncios

El cual nos devuelve lo que vemos en el ejemplo, ahora si procedamos a usar commit:

MariaDB [test]> COMMIT;
Anuncios

Y una vez ejecutado si volvemos a hacer el query anterior nos sucedera lo siguiente:

MariaDB [test]> SELECT * FROM t;
ERROR 1146 (42S02): Table 'test.t' doesn't exist 
Anuncios

Como ejecutamos lo anterior ahora la tabla t ya no existe mas y si tenemos todas las acciones que hicimos en la segunda conexion, para ir finalizando desde la version 10.0 se agregaron algunas opciones a ALTER TABLE:

  • ALGORITHM, se usa para forzar una copia de tabla o se requiere el uso de un algoritmo en-lugar, pero si no se puede usar este tipo de algoritmo nos devuelve un error, por ultimo podemos usar los valores COPY, INPLACE, DEFAULT (que utilizara el mejor algoritmo disponible)
  • ONLINE, equivale a utilizar ALGORITHM=INPLACE
  • LOCK, esta nos permite establecer que no se utilice bloqueos (NONE), solo bloqueos compartidos (READ) o solo bloqueos exclusivos (WRITE), siempre se usara el mejor y en caso de no poder ser implementado nos devolvera un error.
Anuncios

Veamos unos ejemplos de como implementarlos:

ALTER ONLINE TABLE t ADD INDEX idx1 (nombre_col);
Anuncios
ALTER TABLE ALGORITHM = INPLACE, LOCK = NONE ADD INDEX idx1 (nombre_col);
Anuncios

En resumen, hoy hemos visto los bloqueos de metadatos, que son, como trabajan, para que se usan, como nos pueden beneficiar y algunas particularidades sobre los mismos, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50