10 de Junio, 2008

Número máximo de ficheros abiertos y MySQL

No hace mucho tuve problemas con tablas corruptas en MySQL, y no sabía porqué pasaba. Incluso me pasó una segunda vez, con cagada por mi parte :D.

Hoy ha vuelto a pasar, y no habían tablas corruptas, solo vi en los logs:

080610  2:47:49 /usr/local/libexec/mysqld: Can't find file: './blackshell/tblNoticia.frm' (errno: 9)

Junto al ya conocido:

Can't create/write to file '/tmp/#sql_2aa1_0.MYD'

He ejecutado un mysqlcheck (en caliente, con mysqld funcionando), y luego myisamchk en frío... y todas las tablas estaban perfectamente. WTF?!?!

Así que he buscado un poco más y me encontrado esto: 'File' Not Found and Similar Errors.

Vaya :(.

Por defecto OpenBSD tiene un límite muy conservativo de 128 ficheros abiertos para los procesos de la clase daemon.

Mi servidor no aguanta mucha carga, así que es posible que nunca se haya dado el problema hasta sufrir algún pico de actividad. Tengo pocas tablas en el blog, y se tiene que dar mucha concurrencia para que necesite tener más ficheros abiertos de lo normal:

# fstat | grep _mysql | wc -l 
      22 

Tampoco estoy seguro de que este sea el problema, pero ajustar el valor es fácil.

Primero creamos una clase en /etc/login.conf:

_mysql:\
        :ignorenologin:\
        :datasize-cur=infinity:\
        :datasize-max=infinity:\
        :openfiles-cur=512:\
        :openfiles-max=1024:\
        :stacksize-cur=8M:\
        :localcipher=blowfish,8:\
        :tc=default:

He llamado a la clase igual que al usuario para aclararme, aunque no es necesario.

He resaltado los valores más interesantes, teniendo en cuenta que la salida de ejecutar sysctl kern.maxfiles es kern.maxfiles=1772, con lo que usando 1024 de máximo estamos dentro de unos límites correctos.

Ahora hay que cambiar la clase del usuario con chpass _mysql, indicando en Class nuestra nueva clase (_mysql), en lugar de daemon.

Será necesario actualizar /etc/login.conf.db ejecutando:

# cap_mkdb /etc/login.conf

Finalmente añadimos como parámetro a mysqld_safe en la linea de comandos --open-files=1024, y ya tenemos todo en condiciones.

No es necesario reiniciar la máquina para que mysqld_safe, al dejar privilegios para correr como el usuario _mysql, tome la nueva clase. Podemos comprobarlo con:

# su -m _mysql
ksh: Cannot determine current working directory
# ulimit -a
time(cpu-seconds)    unlimited
file(blocks)         unlimited
coredump(blocks)     unlimited
data(kbytes)         1048576
stack(kbytes)        8192
lockedmem(kbytes)    147070
memory(kbytes)       439740
nofiles(descriptors) 512
processes            64

Aclarar que el -m es necesario porque el usuario _mysql no tiene shell, y queremos que su tome algunos valores del entorno de root.

No es una tarea administrativa habitual, y hacía años que no me veía obligado a hacer un cambio así, pero en sistemas BSD puede pasar, y usar login.conf me ha parecido un método con algo más de clase que usar ulimit -n nficheos :D.

A ver si esto soluciona el problema y no vuelvo a tener problemas con MySQL ;).

Anotación por Juan J. Martínez, clasificada en: openbsd, mysql.

Hay 1 comentario

Gravatar

Eso me pasó ayer con un dump de base de datos, al intentar volcar una de las bases con miles de tablas me soltaba eso. Y hasta que encontré que el motivo no era corrupción, lo pasé de mal...

por Hilario Ortigosa, en 2008-06-11 08:20:20

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: