viernes, octubre 17, 2008

MySQL InnoDB y Raw Devices

Estamos trabajando en un proyecto bastante grande y uno de los principales temas a tratar son los de performance. Por un lado estamos teniendo mucho cuidado en tratar de que los programas queden óptimos aparte de prestar mucho cuidado a la utilización de índices y todo lo que ayude a que los programas tengan una buena performance.

Del punto de vista de GeneXus tenemos todo bajo control pero en ocasiones los proyectos son tan grandes que también hay que prestar mucha atención al hardware sobre el cual se va a montar la aplicación y también al “tunning” que se le haga al DBMS.

En la mayoría de los casos no tengo la oportunidad de dedicarme al “tunning” del DBMS pero en este caso quise hacerlo ya que vamos a utilizar MySQL y nos entregaron un servidor con la instalación por defecto.

Lo primero que hice fue actualizar la versión de MySQL ya que el servidor tenía MySQL 5.0 por lo que me baje el rpm para RedHat de la 5.1.28. Desinstale la versión 5.0 mediante rpm y levante la versión nueva.

Tenía un disco de 408 GB para el MySQL por lo que decidí utilizar raw devices para montar los innodb, la idea era crear un Tablespace de 408 GB para MySQL. Lamentablemente después de probar varias veces si creaba un solo archivo de 408 GB se me partía y no me levantaba el servicio, por cuestiones de tiempo no pude investigar mucho mas por lo que decidí crear 4 raw devices de 95 GB cada uno y tener 4 innodb.

Tuve que tocar el my.cnf con todos los parámetros que pongo habitualmente para trabajar con innodb solo que cambie la parte de innodb_data_file_path para montar los raw devices.


Actualmente el my.cnf lo tengo así:

innodb_data_file_path = /dev/raw/raw1:95Graw;/dev/raw/raw2:95Graw;/dev/raw/raw3:95Graw;/dev/raw/raw4:95Graw

Lo interesante fue que tuve que particionar el disco y crear los raw devices, a pesar de mi nick no soy experto en linux por lo que tuve que apoyarme en mi amigo “google” para poder cumplir esta tarea.

Las particiones las hice con fdisk y me quedo de la siguiente manera:
Device Boot Start End Blocks Id System
/dev/sdb1 1 12405 99643131 83 Linux
/dev/sdb2 12406 24808 99627097+ 83 Linux
/dev/sdb3 24809 37214 99651195 83 Linux
/dev/sdb4 37215 49605 99530707+ 83 Linux

Para crear los raw devices tuve que hacer lo siguiente:
Editar el /etc/udev/rules.d/60-raw.rules y escribir las siguientes líneas:

ACTION=="add", KERNEL=="sdb1", RUN+="/bin/raw /dev/raw/raw1 %N"
ACTION=="add", KERNEL=="sdb2", RUN+="/bin/raw /dev/raw/raw2 %N"
ACTION=="add", KERNEL=="sdb3", RUN+="/bin/raw /dev/raw/raw3 %N"
ACTION=="add", KERNEL=="sdb4", RUN+="/bin/raw /dev/raw/raw4 %N"

Editar el archivo /etc/udev/rules.d/ 41-local-permissions-rules y agregar las siguientes líneas:

KERNEL=="sdb1" GROUP="mysql"
KERNEL=="sdb2" GROUP="mysql"
KERNEL=="sdb3" GROUP="mysql"
KERNEL=="sdb4" GROUP="mysql"

El problema que tuve es que al re-iniciar el equipo los raw devices quedaban con el owner root por lo que MySQL no tenía permisos para usarlos. Después de unos minutos sin encontrar una solución elegante lo que hice fue emplear una solución desprolija pero que funciono. :-)

Edite el archivo /etc/init.d/mysql en donde agregue las siguientes líneas:

chown mysql /dev/raw/raw1
chown mysql /dev/raw/raw2
chown mysql /dev/raw/raw3
chown mysql /dev/raw/raw4

No se si la solución es la mas elegante pero quedo funcionando y pude seguir adelante.


Una vez que tuve los raw creados y con permisos para mysql lo que hice fue modificar el my.cnf de la siguiente manera:

innodb_data_file_path = /dev/raw/raw1:95Gnewraw;/dev/raw/raw2:95Gnewraw;/dev/raw/raw3:95Gnewraw;/dev/raw/raw4:95Gnewraw

El newraw le indica a mysql que tiene que crear el espacio de tablas por lo que una vez que tenemos el my.cnf configurado alcanza con bajar y subir el servicio mysql para que me cree el espacio de datos en los raw devices que se le indicarón.

Una vez que mysql termino hay que modificar el my.cnf para que quede de la siguiente manera:

innodb_data_file_path = /dev/raw/raw1:95Graw;/dev/raw/raw2:95Graw;/dev/raw/raw3:95Graw;/dev/raw/raw4:95Graw

Un consejo es que cuando mysql esta creando el espacio de tables nos da un Failed pero sigue trabajando por lo que una forma que tenemos de saber si todavía se encuentra trabajando es hacer un ls –l /dev/raw/ esto me tira lo siguiente:

crw------- 1 mysql root 162, 1 Oct 12 18:16 raw1
crw------- 1 mysql root 162, 2 Oct 13 11:12 raw2
crw------- 1 mysql root 162, 3 Oct 13 11:30 raw3
crw------- 1 mysql root 162, 4 Oct 13 11:49 raw4
En mi caso como el tamaño de los innodb era de 95 GB al levantar mysql después de 5 minutos me daba un Failed pero seguía trabajando y la forma que tuve de saber en que iba era haciendo el ls para consultar la hora de modificación. Un experto seguramente tenga otros métodos pero no es mi caso.

Con esto tenemos mysql utilizando particiones crudas como se dice habitualmente.

4 comentarios:

Anónimo dijo...

Interesantísimo el artículo. Se agradece que hayas compartido tanta información.
Ahora, nosotros tenemos un problema muy parecido, y creo que tenemos que acudir a ti por los conocimientos que demostrás.
El problema es que manejamos un Cluster de dos nodos que tiene que empezar a levantar a mysql como base de datos.
Para compartir el Storage debemos utilizar GFS (global file system, de Centos), la pregunta es: ¿podemos utilizar la tecnología RAW para darle los discos enteros a mysql en el cluster?

Santiago Pomata dijo...

Excelentes comentarios! gracias por compartir. Saludos desde Paraguay!!!

Anónimo dijo...

Está muy interesante el artículo, es de mucha ayuda esta información para convertir las particiones primarias en particiones de raw device. En mi caso para que el nodo pueda ver las 'particiones crudas' como storage.

carlos dijo...

Creo que la solución prolija es cambiarle el dueño en el mismo fstab con las opciones uid y gid para poner el usuario correcto (el id del usuario lo encuentras en /etc/passwd)

Saludos