MySQL WTF

De frikis/{ Hacking | Curiosidades } — 18/08/2009 @ 22:25

Mysql es una base de datos Open Source fiable y rápida. Ideal para la llamada “Web 2.0″ (o 3.0, no se por qué número vamos ya). Las grandes plataformas web no pueden depender de una base de datos relacional al estilo tradicional. Los datos se encuentran particionados en diferentes tablas, cada tabla casi en su propia granja de servidores. Los conceptos de Foreign Key, integridad referencial, normalización, etc. tan venerados por los diseñadores de bases de datos no tienen sentido. Ninguna base de datos ni máquina puede escalar a los niveles que necesitan las grandes plataformas web.

La responsabilidad sobre la lógica, la gestión de los datos, la gestión de la integridad se desplaza a los frontales, el código de la aplicación, instalado en cientos de servidores, y que por tanto escala casi linealmente frente al cuello de botella de las bases de datos.

Por ello mysql con su sencillez y orientación a la velocidad se posiciona como alternativa interesante, apoyada por sistemas de caché key-value (de nuevo nada relacionales) como Memcached. Incluso existen forks (por importantes divergencias en la forma de llevar el desarrollo) como Drizzle o Maria DB que incluso recortan aún más las funcionalidades para poder avanzar en el camino de la escalabilidad.

Pero MySQL también tiene cosas malas. Como este bug por el que hemos perdido horas y horas de investigación en tuenti. Al cambiar unas tablas de MyISAM a InnoDB empezamos a observar cómo el esclavo migrado se empezaba a retrasar respecto al maestro, totalmente saturado con las consultas y el thread de replicación consumiendo el 100% de uno de los cores.

Un ejemplo lo resume todo:

mysql> SELECT * FROM test WHERE int_field=1 and bigint_field=1;
Empty set (0.00 sec)

mysql> SELECT * FROM test WHERE (int_field,bigint_field) IN ((1,1)); Empty set (0.00 sec)

mysql> DELETE FROM test WHERE int_field=1 and bingint_field=1; Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM test WHERE (int_field,bingint_field) IN ((1,1)); Query OK, 0 rows affected (1.19 sec) ^…………………………….. WTF!!!

El problema de rendimiento ocurre cuando se utiliza la sintaxis IN, sólo si hay dos o más campos en el IN, sólo si al menos uno de los campos es BIGINT. Un conjunto de condiciones cuanto menos curioso. Cambiando la sintaxis de las queries, problema resuelto…

El problema es especialmente notable cuando la tabla es InnoDB. Con MyISAM el cuatro query tarda 0.19sec, mejor, pero un tiempo todavía absurdo comparado con los tiempos de los otros queries. ¡Deberían comportarse todos igual! Definitivamente hay algo roto en los entresijos del servidor para tener un rendimiento tan horrible.

Diario de sueños de Guillermo Pérez (aka bisho)