Inserciones concurrentes en tablas MyISAM de MySQL

Mysql soporta la inserción de registros en una tabla con engine MyISAM al mismo tiempo que se realizan consultas sobre la misma. Es decir, se pueden ejecutar sentencias SELECT mientras se están concretando sentencias INSERT. En un principio esto parece ser muy bueno pero tenemos que tener algunas consideraciones.

Existe una variable de configuración que controla este comportamiento: concurrent_insert. La misma puede tomar los siguientes valores a partir de Mysql 5.5.3 (entre paréntesis se indica el valor correspondiente en versiones previas):

  • NEVER (0): desactiva los INSERTs concurrentes
  • AUTO (1): activa los INSERTs concurrentes solamente para las tablas MyISAM no tengan huecos.
    • Cuando los huecos de una tabla se completan, se vuelven a activar las inserciones concurrentes en esa tabla.
    • Es el valor por defecto.
  • ALWAYS (2): activa los INSERTs concurrentes para TODAS las tablas MyISAM (aunque tengan huecos).
    • Si la tabla tiene huecos y está siendo utilizada por otro proceso (thread), las filas nuevas se agregan al final de la tabla.
    • De lo contrario, se lockea la tabla y se intenta llenar los huecos.

Ejemplo

mysql> SELECT @@GLOBAL.concurrent_insert;

-> AUTO

Además, los resultados de las inserciones podrían no ser visibles instantáneamente, dado que si existen muchas se encolan y se tratan secuencialmente, en simultaneidad con las consultas.

Basado en:

http://dev.mysql.com/doc/refman/5.5/en/concurrent-inserts.htm

Anuncios

Cómo funcionan las zonas horarias en MySQL

Variables de timezone definidas

Mysql establece el timezone o zonas horaria en distintas variables de sistema, las cuales sirven a diferentes propósitos.

Timezone del sistema

Se determina cuando el servidor inicia y se almacena en la variable global system_time_zone.

mysql> SELECT @@global.system_time_zone;

-> Hora estándar de Argentina

Timezone del servidor

Se almacena en la variable global time_zone e indica el timezone en el cual está operando el servidor. Por defecto, su valor es SYSTEM, lo que significa que es el mismo que el system_time_zone.

mysql> SELECT @@global.time_zone;

-> SYSTEM

Se puede cambiar su valor mediante

mysql> SET @@global.time_zone = 'timezone';

Timezone de la conexión

Se almacena en la variable de sesión time_zone e indica el timezone en el cual está operando la conexión. Por defecto, su valor es el de la variable global time_zone.

mysql> SELECT @@session.time_zone;

-> SYSTEM

Se puede cambiar su valor mediante

mysql> SET @@session.time_zone = 'timezone';

Valores de ‘timezone’ permitidos

Cuando debemos establecer un timezone podemos optar por los siguientes tipos de valor:

  • Offset de UTC
  • Nombre de zona horaria
  • Valor ‘SYSTEM’

Las zonas horarias nombradas disponibles en Mysql se pueden obtener mediante:

mysql> USE mysql;

mysql> SELECT name FROME time_zone_name;

Si no obtenemos ningún resultado, entonces deberemos cargar las zonas horarias en Mysql.

Uso de los timezones en Mysql

El campo de tipo TIMESTAMP convierte el valor desde el timezone de sesión a UTC para guardarlo y de UTC al timezone de sesión al devolverlo. También se utiliza el timezone de la sesión actual para el valor obtenido al invocar ciertas funciones, como por ejemplo, la función NOW().

Los campos de tipo DATE, TIME y DATETIME no se ven afectados por el timezone de la sesión como tampoco funciones asociadas a UTC, como puede ser UTC_TIMESTAMP().

Conocer el modo actual de MySQL (y cambiarlo)

El modo actual de Mysql se encuentra en la variable de sistema sql_mode.

Conocer el modo actual

Para ver el modo en el que Mysql está trabajando, debemos consultar la variable de sistema sql_mode. Para ello, abrimos una conexión al servidor mysql y ejecutamos:

SELECT @@global.sql_mode; #Modo global, a nivel servidor

SELECT @@session.sql_mode; #Modo de la sesión en curso

Estas son algunas de las formas de consultar el valor de una variable de sistema.

Ejemplo:

mysql> SELECT @@global.sql_mode;
+----------------------------------------------------------------+
| @@global.sql_mode                                              |
+----------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)

Cambiar el modo

Si deseamos cambiar el modo por otro debemos modificar la variable de sistema sql_mode. Antes de proceder, necesitamos conocer los modos disponibles según la versión de Mysql con la que estemos trabajando. A continuación abrimos una conexión al servidor mysql y ejecutamos:

SET @@global.sql_mode = 'MODOS_SEPARADOS_POR_COMA';

SET @@session.sql_mode = 'MODOS_SEPARADOS_POR_COMA';

Estas son algunas de las formas de establecer el valor de una variable de sistema.

Ejemplo:

mysql> SET @@global.sql_mode= 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)

Luego, reiniciamos la conexión con el servidor mysql.

Variables de sistema en MySQL

Mysql tiene muchas variables de sistema que indican cómo está configurado. Cada una tiene un valor por defecto y la mayoría puede ser modificada dinámicamente mientras el servidor está corriendo.

Existen de dos tipos:

  • Globales: afectan la operación del servidor completo
  • de Sesión: afectan la operación de las conexiones cliente individuales

Cuando el servidor inicia, establece todas las variables globales a su valor por defecto. Cuando se inicia una conexión desde un cliente, sus variables de sesión se inicializan usando los valores actuales de las correspondientes variables globales.

Reglas para consultar o establecer el valor de una variable de sistema

  • Variable global: se precede su nombre con GLOBAL o @@global
  • Variable de sesión:
    • se precede su nombre por SESSION, @@session o @@
    • se precede su nombre por LOCAL o @@local
    • no se utiliza ningún modificador (solamente válido para establecer el valor)

Alternativamente se puede utilizar SHOW VARIABLES LIKE ‘variable’, donde se permiten comodines para obtener los valores de varias variables similares.

Ejemplo: Para obtener todas aquellas que definen un charset:

SHOW VARIABLES LIKE 'character_set%'

 

Consultar el valor de una variable de sistema

Si la variable es de sesión:

SELECT @@session.variable;
SELECT @@local.variable;
SELECT @@variable; #Devuelve el valor de la sesión si existe. De lo contrario el global!
SHOW SESSION VARIABLES LIKE 'variable';
SHOW LOCAL VARIABLES LIKE 'variable';
SHOW VARIABLES LIKE 'variable';

Si la variable es global:

SELECT @@GLOBAL.variable;
SHOW GLOBAL VARIABLES LIKE 'variable';

Establecer el valor de una variable de sistema

Si la variable es de sesión:

SET @@session.variable = 'valor';
SET @@local.variable = 'valor';
SET @@variable = 'valor';
SET SESSION variable = 'valor';
SET LOCAL variable = 'valor';
SET variable = 'valor';

El valor se mantiene durante esa sesión (o hasta que se cambie) y no es visible para otros clientes.

Si la variable es global:

SET @@global.variable = 'valor';
SET GLOBAL variable = 'valor';

Se requiere tener el privilegio SUPER para poder cambiar valores de variables globales.

El nuevo valor aplica solamente clientes que se conecten luego del cambio (no afecta las variables de sesión de ningún cliente previamente conectado)