Clicky

Cómo aumentar de forma permanente archivos abiertos 'open_files_limit' en MySQL

open files limit

[Warning] Could not increase number of max_open_files to more than 1024 (request: )

Cuando monto un servidor web suelo configurar varias copias de seguridad programadas diariamente para el caso de que si hay algún problema podamos recurrir a ellas y recuperar nuestros archivos y las bases de datos. Lo más normal es que los backups los tengamos dentro de alguna partición del disco duro de nuestro servidor y hagamos periódicamente una descarga a nuestro PC dependiendo de las características de cada sitio web y el grado en que cambia cada uno.

También utilizo un backup automatizado a un sitio de almacenamiento en la nube, en mi caso trabajo con Amazon S3 que permite hacer un respaldo incremental de los archivos y bases de datos guardando sólo los últimos cambios.

Al configurar un nuevo Bucket en Amazon para este propósito en un nuevo servidor me estaban dando errores de MYSQL en el motor que utilizo, MariaDB, y se caía el demonio y claro está todas las páginas web que tengo de momento en pruebas. Los errores eran de este tipo:

En el log de MariaDB:

•  [Warning] Could not increase number of max_open_files to more than 1024 (request: 4721)

En la salida de la copia de seguridad en Virtualmin:

•  Dumping MySQL database camerweb ..

.. dump failed!

mysqldump: Couldn't execute 'SHOW TRIGGERS LIKE 'bzgb2\_updates'': Can't read dir of './camerweb/' (errno: 24) (1018)

•  Dumping MySQL database camerweb ..
.. dump failed!

Out of resources when opening file './camerweb/bzgb2_usergroups.MYD' (Errcode: 24) SQL=SELECT b.id FROM bzgb2_usergroups AS a LEFT JOIN bzgb2_usergroups AS b ON b.lft <= a.lft AND b.rgt >= a.rgt WHERE a.id = 9

Y en la propia página web:

•  23 - Out of resources when opening file './camerweb/bzgb2_assets.MYD' (Errcode: 24) SQL=SELECT b.rules FROM bzgb2_assets AS a LEFT JOIN bzgb2_assets AS b ON b.lft <= a.lft AND b.rgt >= a.rgt WHERE (a.name = 'com_content.category.13') GROUP BY b.id, b.rules, b.lft ORDER BY b.lft

La solución a estos errores es aumentar el límite de los archivos abiertos del sistema, por que si sólo aumentamos el open_files_limit en el archivo de configuración de MYSQL /etc/my.cnf no surte efecto. Vemos porqué y cómo corregirlo:

El ulimit o límite de los archivos abiertos por defecto (como máximo) es 1024 - que es muy bajo, especialmente para un entorno de servidor de alojamiento web con varios sitios que soportan grandes bases de datos.

Este ajuste de ulimit 'archivos abiertos' también es utilizado por MySQL. MySQL cambia automáticamente su open_files_limit al ulimit del sistema que se establece en el por defecto y será 1024.

NOTA: MySQL NO puede establecer su open_files_limit a algo mayor que lo que se precisa en ulimit 'archivos abiertos' - se puede configurar más bajo, pero no por encima de límite de los archivos abiertos del sistema.

Así es como se plantea el ulimit

Para comprobar los límites:

# ulimit -a

Veremos algo como:

core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 257403
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 257403
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

O si lo que deseamos es ver el límite en menos de los "archivos abiertos" bajo el usuario que está conectado actualmente haremos:

# ulimit -n

O para ver los límites de archivos abiertos soft y hard de forma individual:

# ulimit -Hn
# ulimit -Sn

Y si deseams comprobar el límite para MySQL en particular, haremos:

# mysql -u root -p

Una vez en el símbolo MySQL

MariaDB [(none)]>

Introducimos lo siguiente:

# show global variables like 'open%';

Se debería ver lo siguiente:

+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| open_files_limit | 1024 |
+------------------+--------+
1 row in set (0.00 sec)

Ahora vamos fijar permanentemente el límite de los "archivos abiertos"

Para establecer el límite máximo de los límites disponibles (un límitemáximo soft o hard puede ser establecido para cada usuario).

NOTA: esto se establece por un PAM durante la autenticación, y no en el arranque. (Véase más adelante para efectuar el trabajo).

Agrega lo siguiente al final del archivo /etc/security/limits.conf para establecerlos para todos * :

* soft nofile 1024000
* hard nofile 1024000
* soft nproc 10240
* hard nproc 10240

Para establecerlos solamente para un usuario específico, como MySQL, poner esto:

mysql hard nofile 1024000
mysql soft nofile 1024000

Repetir el proceso para /etc/security/limits.d/20-nproc.conf (el número de este archivo puede ser diferente en tu caso)

Agrega lo siguiente:

* soft nofile 1024000
* hard nofile 1024000
* soft nproc 10240
* hard nproc 10240
root soft nproc unlimited

He escogido '1024000', que es bastante alto; seguramente se puede establecer más bajo, a algo así como '102400'

Para establecer temporalmente el límite de los archivos abiertos en menos para el usuario que ha iniciado sesión (por ejemplo, 'root'):

# ulimit -Hn 1024000

Ahora nos fijamos en la línea open_files_limit en my.cnf (MySQL) - por lo que los valores se cargan durante el arranque (después de reiniciar el servidor).

Curiosamente, el open_files_limit en mysql no se ajustará automáticamente en el arranque a lo que pusimos en /etc/security/limits.conf, a menos que se especifique en /etc/my.cnf .

Sin embargo, cargará los valores si se reinicia manualmente a través de systemctl restart mariadb.service, incluso si no está en /etc/my.cnf . Estoy pensando que esto tiene que ver con la autenticación PAM, donde los valores de /etc/my.cnf se cargan DESPUÉS de que se haya cargado /etc/security/limits.conf .

En fin... a ello:

Editamos: vi /etc/my.cnf

Insertamos lo siguiente debajo de [mysqld] :

[mysqld]
open_files_limit = 1024000

Como alternativa también se puede simplemente establecer el valor bajo [mysqld_safe] , y esto también va a establecer el valor en el arranque:

[mysqld_safe]
open_files_limit = 1024000

Ahora reiniciamos mysqld (MariaDB):

# systemctl restart mariadb.service

Ahora vamos a ver si MySQL está usando los nuevos valores:

# mysql -u root -p

Una vez en el símbolo MySQL

MariaDB [(none)]>

Introducimos lo siguiente:

# show global variables like 'open%';

Se debería ver lo siguiente:

+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| open_files_limit | 1024000 |
+------------------+--------+
1 row in set (0.00 sec)

¡Guay! Funciona.

A continuación, debemos reiniciar el servidor y repetir los pasos de MySQL de arriba para asegurarnos de que se están cargando en el arranque.

 

# mysql -u root -p 
# show global variables like 'open%';

Si, después del arranque, se muestra que el sistema por defecto es 1024, eso significa que mysqld no aplica la configuración en el arranque.

Por favor continúa a continuación en la sección de solución de problemas.

Solución de problemas y notas

El proceso mysqld debe de forma automática usar/aplicar open_files_limit en relación con lo que se aplica en virtud de ulimit o /etc/security/limits.conf (véase más arriba).

Es decir, si tenemos lo siguiente en /etc/security/limits.conf :

* hard nofile 102400
* soft nofile 102400

O si se establece el límite temporal a través de:

# ulimit -Hn 102400

El servidor MySQL utilizará automáticamente el valor bajo open_files_limit cuando se reinicia, siempre y cuando sean iguales o inferiores al límite de los archivos abiertos.

Sin embargo, desde mi hallazgo en el arranque (después del reinicio) - bajo uno de mis servidores (podría ser diferente para los demás) - los valores de /etc/security/limits.conf se cargan después mysqld se inicia en el arranque. Es decir, mysqld no recibe los valores actualizados, y en su lugar utiliza el valor por defecto 1024.

/etc/security/limits.conf se carga en la autenticación PAM y no en el momento del arranque.

Una solución: simplemente reiniciar mysqld después se inicia el sistema.

Otra solución consiste en establecer estos valores en el arranque antes de todo lo demás (permanente):

# vi /etc/init.d/mysqld (en Centos 7 con Apache 2.4.6, PHP 7 y MariaDB sería: /usr/lib/systemd/system/mariadb.service )

Agrega lo siguiente:

ulimit -S -n ${DAEMON_FILES_LIMIT:-102400} >/dev/null 2>&1

O bien, como se señaló anteriormente (si se ha saltado directamente a la sección de solución de problemas) agregar esto a tu /etc/my.cnf

[myqld_safe]
open_files_limit = 102400

O

[myqld]
open_files_limit = 102400

Jesus_Caceres