Capítulo 14. Motores de almacenamiento de MySQL y tipos de tablas

MySQL 5.0

Capítulo 14. Motores de almacenamiento de MySQL y tipos de tablas

MySQL soporta varios motores de almacenamiento que tratan con distintos tipos de tabla. Los motores de almacenamiento de MySQL incluyen algunos que tratan con tablas transaccionales y otros que no lo hacen:

  • trata tablas no transaccionales. Proporciona almacenamiento y recuperación de datos rápida, así como posibilidad de búsquedas fulltext. se soporta en todas las configuraciones MySQL, y es el motor de almacenamiento por defecto a no ser que tenga una configuración distinta a la que viene por defecto con MySQL.

  • El motor de almacenamiento proporciona tablas en memoria. El motor de almacenamiento permite una colección de tablas idénticas ser tratadas como una simple tabla. Como , los motores de almacenamiento y tratan tablas no transaccionales y ambos se incluyen en MySQL por defecto.

    Nota: El motor de almacenamiento anteriormente se conocía como .

  • Los motores de almacenamiento y proporcionan tablas transaccionales. se incluye en la distribución binaria MySQL-Max en aquellos sistemas operativos que la soportan. también se incluye por defecto en todas las distribuciones binarias de MySQL 5.0 . En distribuciones fuente, puede activar o desactivar estos motores de almacenamiento configurando MySQL a su gusto.

  • El motor de almacenamiento es un motor de almacenamiento "tonto" que no hace nada. Puede crear tablas con este motor, pero no puede almacenar datos ni recuperarlos. El objetivo es que sirva como ejemplo en el código MySQL para ilustrar cómo escribir un motor de almacenamiento. Como tal, su interés primario es para desarrolladores.

  • es el motor de almacenamiento usado por MySQL Cluster para implementar tablas que se particionan en varias máquinas. Está disponible en distribuciones binarias MySQL-Max 5.0. Este motor de almacenamiento está disponible para Linux, Solaris, y Mac OS X . Añadiremos soporte para este motor de almacenamiento en otras plataformas, incluyendo Windows en próximas versiones.

  • El motor de almacenamiento se usa para guardar grandes cantidades de datos sin índices con una huella muy pequeña.

  • El motor de almacenamiento guarda datos en ficheros de texto usando formato de valores separados por comas.

  • El motor de almacenamiento se añadió en MySQL 5.0.3. Este motor guarda datos en una base de datos remota. En esta versión sólo funciona con MySQL a través de la API MySQL C Client. En futuras versiones, será capaz de conectar con otras fuentes de datos usando otros drivers o métodos de conexión clientes.

Este capítulo describe cada uno de los motores de almacenamiento MySQL excepto y , que se tratan en Capítulo 15, El motor de almacenamiento y Capítulo 16, MySQL Cluster.

Cuando crea una nueva tabla, puede decirle a MySQL qué tipo de tabla crear añadiendo la opción de tabla o al comando :

CREATE TABLE t (i INT) ENGINE = INNODB;
CREATE TABLE t (i INT) TYPE = MEMORY;

Aunque se soporta en MySQL 5.0, es el término preferido.

Si omite la opción o , se usa el motor de almacenamiento por defecto, que es . Puede cambiarlo usando las opciones de arranque o , o cambiando la variable de sistema o .

Cuando se instala MySQL en Windows usando el MySQL Configuration Wizard, es el motor de almacenamiento por defecto en lugar de . Consulte Sección 2.3.5.1, “Introducción”.

Para convertir una tabla de un tipo a otro, use un comando que indique el nuevo tipo:

ALTER TABLE t ENGINE = MYISAM;
ALTER TABLE t TYPE = BDB;

Consulte Sección 13.1.5, “Sintaxis de y Sección 13.1.2, “Sintaxis de .

Si trata de usar un motor de almacenamiento que no está compilado o que está desactivado, MySQL crea una tabla de tipo . Este comportamiento es conveniente cuando quiere copiar tablas entre servidores MySQL que soportan distintos motores. (Por ejemplo, en una inicialización de replicación, tal vez su maestro suporte un motor de almacenamiento transaccional para más seguridad, pero los esclavos usan un motor de almacenamiento no transaccional para mayor velocidad.)

La sustitución automática del tipo cuando se especifica un tipo no especificado puede ser confuso para nuevos usuarios. En MySQL 5.0, se genera una advertencia cuando se cambia un tipo de tabla automáticamente.

MySQL siempre crea un fichero para guardar la definición de tabla y columnas. El índice y datos de la tabla puede estar almacenado en uno o más ficheros, en función del tipo de tabla. El sevidor crea el fichero por encima del nivel de almacenamiento del motor. Los motores de almacenamiento individuales crean los ficheros adicionales necesarios para las tablas que administran.

Una base de datos puede contener tablas de distintos tipos.

Las tablas transaccionales (TSTs) tienen varias ventajas sobre las no transaccionales (NTSTs):

  • Más seguras. Incluso si MySQL cae o tiene problemas de hardware, puede recuperar los datos, mediante recuperación automática o desde una copia de seguridad más el log de transacciones.

  • Puede combinar varios comandos y aceptarlos todos al mismo tiempo con el comando (si autocommit está desactivado).

  • Puede ejecutar para ignorar los cambios (si autocommit está desactivado).

  • Si falla una actualización, todos los cambios se deshacen. (Con tablas no transaccionales, todos los cambios son permanentes.)

  • Motores de almacenamiento transaccionales pueden proporcionar mejor concurrencia para tablas que tienen varias actualizaciones concurrentes con lecturas.

En MySQL 5.0, usa valores de configuración por defecto si no los especifica. Consulte Sección 15.3, “Configuración de .

Tablas no transaccionales tienen varias ventajas al no tener una sobrecarga transaccional:

  • Más rápidas

  • Menor requerimiento de espacio.

  • Menos memoria para actualizaciones

Puede combinar tablas transaccionales y no transaccionales en el mismo comando para obtener lo mejor de ambos mundos. Sin embargo, en una transaccion con autocommit desactivado, los cambios de tablas no transaccionales son permanentes inmediatamente y no pueden deshacerse.

14.1. El motor de almacenamiento MyISAM

es el motor de almacenamiento por defecto. Se basa en el código pero tiene muchas extensiones útiles. (Tenga en cuenta que MySQL 5.0 no soporta .)

Cada tabla se almacena en disco en tres ficheros. Los ficheros tienen nombres que comienzan con el nombre de tabla y tienen una extensión para indicar el tipo de fichero. Un fichero almacena la definición de tabla. El fichero de datos tiene una extensión () . El fichero índice tiene una extensión () .

Para especificar explícitamente que quiere una tabla , indíquelo con una opción :

CREATE TABLE t (i INT) ENGINE = MYISAM;

(Nota: Antinguas versiones de MySQL usaban en lugar de (por ejemplo: ). MySQL 5.0 soporta esta sintaxis para compatibilidad con versiones anteriores pero está obsoleto y ahora se usa .)

Normalmente, la opción no es necesaria; es el motor de almacenamiento por defecto a no ser que se cambie.

Puede chequear o reparar tablas con la utilidad myisamchk . Consulte Sección 5.8.3.7, “Usar myisamchk para recuperación de desastres”. Puede comprimir tablas con myisampack para que ocupen mucho menos espacio. Consulte Sección 8.2, “myisampack, el generador de tablas comprimidas de sólo lectura de MySQL”.

Las siguientes son algunas características del motor de almacenamiento :

  • Todos los datos se almacenan con el byte menor primero. Esto hace que sean independientes de la máquina y el sistema operativo. El único requerimiento para portabilidad binaria es que la máquina use enteros con signo en complemento a dos (como todas las máquinas en los últimos 20 años) y formato en coma flotante IEEE (también dominante en todas las máquinas). La única área de máquinas que pueden no soportar compatibilidad binaria son sistemas empotrados, que a veces tienen procesadores peculiares.

    No hay penalización de velocidad al almacenar el byte menor primero; los bytes en un registro de tabla normalmente no están alineados y no es un problema leer un byte no alineado en orden normal o inverso. Además, el código en el servidor que escoge los valroes de las columnas no es crítico respecto a otro código en cuanto a velocidad.

  • Ficheros grandes (hasta longitud de 63 bits) se soportan en sistemas de ficheros y sistemas operativos que soportan ficheros grandes.

  • Registros de tamaño dinámico se fragmentan mucho menos cuando se mezclan borrados con actualizaciones e inserciones. Esto se hace combinando automáticamente bloques borrados adyacentes y extendiendo bloques si el siguiente bloque se borra.

  • El máximo número de índices por tabla en MySQL 5.0 es 64. Esto puede cambiarse recompliando. El máximo número de columnas por índice es 16.

  • La longitud máxima de clave es 1000 bytes. Esto puede cambiarse recompilando. En caso de clave mayor a 250 bytes, se usa un tamaño de bloque mayor, de 1024 bytes.

  • Las columnas y pueden indexarse.

  • Valores se permiten en columnas indexadas. Esto ocupa 0-1 bytes por clave.

  • Todos los valores de clave numérico se almacenan con el byte mayor primero para mejor compresión de índice.

  • Cuando se insertan registros en orden (como al usar columnas ), el árbol índice se divide de forma que el nodo mayor sólo contenga una clave. Esto mejora la utilización de espacio en el árbol índice.

  • El tratamiento interno de una columna por tabla. actualiza automáticamente esta colunmna para operaciones y . Esto hace las columnas más rápidas (al menos 10%). Los valores iniciales de la secuencia no se reúsan tras ser borrados. (Cuando una columna se define como la última columna de un índice de varias columnas, se reúsan los valores borrados iniciales de la secuencia.) El valor puede cambiarse con o myisamchk.

  • Si una tabla no tiene bloques libres en medio del fichero de datos, puede nuevos registros a la vez que otros flujos leen de la tabla. (Esto se conoce como inserciones concurrentes.) Un bloque libre puede ser resultado de borrar o actualziar registros de longitud dinámica con más datos que su contenido. Cuando todos los bloques libres se usan (se rellenan), las inserciones futuras vuelven a ser concurrentes.

  • Puede tener el fichero de datos e índice en directorios distintos para obtener más velocidad con las opciones y para . Consulte Sección 13.1.5, “Sintaxis de .

  • Cada columna de carácteres puede tener distintos conjuntos de carácteres. Consulte Capítulo 10, Soporte de conjuntos de caracteres.

  • Hay un flag en el fichero índice que indica si la tabla se ha cerrado correctamente. Si mysqld se arranca con la opción , Las tablas se chequean automáticamente al abrirse, y se reparan si la tabla no se cierra correctamente.

  • myisamchk marca las tablas como chequeadas si se ejecuta con la opción . myisamchk --fast cheque sólo las tablas que no tienen esta marca.

  • myisamchk --analyze almacena estadísticas para partes de las claves, así como para las claves enteras.

  • myisampack puede comprimir columnas y .

soporta las siguientes características:

  • Soporte de un tipo auténtico; una columna comienza con la longitud almacenada en dos bytes.

  • Tablas con pueden tener longitud de registro fija o dinámica.

  • y pueden ser de hasta 64KB.

  • Un índice hash puede usarse para . Esto le permite tener o cualquier combinación de columnas en una tabla . (Sin embargo, no puede buscar en un índice .)

14.1.1. Opciones de arranque de MyISAM

Las siguientes opciones de mysqld pueden usarse para cambiar el comportamiento de tablas :

  • Cambia el modo para recuperación automática para tablas .

  • No vuelca buffers de clave entre escrituras para cualquier tabla .

    Nota: Si hace esto, no debe usar tablas desde otro programa (como otro servidor MySQL server o con myisamchk) cuando la tabla está en uso. Hacerlo provoca corrupción de índice.

    Usar no ayuda para tablas que usan .

Consulte Sección 5.3.1, “Opciones del comando mysqld.

Las siguientes variables de sistema afectan al comportamiento de tablas :

  • Tamaño del árbol de caché usado en optimización de inserciones. Nota: Este es el límite por flujo!

  • Usado para ayudar a MySQL a decidir cuándo usar el método de creación de índice de clave caché lento pero seguro Nota: Este parámetro se daba en bytes antes de MySQL 5.0.6, cuando se eliminó.

  • No usa el método de ordenación de índice rápido para crear un índice si el fichero temporal será más grande a este tamaño. Nota: En MySQL 5.0, este parámetro se da en bytes.

  • Cambia el tamaño del búffer usado al recuperar tablas.

Consulte Sección 5.3.3, “Variables de sistema del servidor”.

La recuperación automática se activa si arranca mysqld con la opción . En ese caso, cuando el servidor abre una tabla , chequea si la tabla está marcada como mal cerrada o si el contador de veces que se ha abierto la tabla no es 0 y está ejecuando el servidor con . Si alguna de estas condiciones es cierta, ocurre lo siguiente:

  • Se chequea la tabla para errores.

  • Si el servidor encuentra un error, trata de hacer una reparación de tabla rápida (ordenando y sin recrear el fichero de datos).

  • Si falla la reparación debido a un error en el fichero de datos (por ejemplo, error de clave duplicada), el servidor lo intenta otra vez, esta vez recreando el fichero de datos.

  • Si sigue fallando, el servidor trata una vez más con el método de reparación antiguo (escrito registro a registro sin ordenar). Este método debe ser capaz de reparar cualquier clase de error y tiene requerimientos de espacio bajos.

Si la recuperación no fuera capaz de recuperar todos los registros de un comando préviamente completado y no ha especificado en la opción , la recuperación automática aborta con un mensaje de error en el log de errores:

Error: Couldn't repair table: test.g00pages

Si especifica , se escribe una advertencia como esta:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

Tenga en cuenta qui el valor de recuperación automático incluye , el proceso de recuperación crea ficheros con nombres de la forma .BAK. Debe tener un script cron que mueva estos ficheros automáticamente del directorio de base de datos al dispositivo de copia de seguridad.

14.1.2. Cuánto espacio necesitan las claves

Tablas usan índices B-tree. Puede calcular el tamaño del fichero índice mediante , sumado sobre todas las claves. Este es el peor caso en que todas las claves se insertan en orden ordenado y la tabla no tienen ninguna clave comprimida.

Los índices de cadenas de carácteres están comprimidos en espacio. Si la primera parte del índice es una cadena de carácteres, también tiene el prefijo comprimido. La compresión de espacio hace que el fichero índice sea menor que el peor caso si la columna de la cadena de carácteres tiene muchos espacios finales o es una columna que no se usa siempre con la longitud total. La compresión de prefijo se usa en claves que comienzan con una cadena de carácteres. La compresión de prefijo ayuda si hay muchas cadenas de carácteres con un prefijo idéntico.

En tablas puede comprimir números prefijo especificando cuando crea la tabla. Esto ayuda cuando tiene muchas claves enteras con un prefijo idéntico cuando los números se almacenan con el byte mayor primero.

14.1.3. Formatos de almacenamiento de tablas MyISAM

soporta tres formatos de almacenamiento distintos. Dos de ellos (formato fijo y dinámico) se eligen automáticamente en función del tipo de columnas que esté usando. El tercero, formato comprimido, puede ser creado sólo con la utilidad myisampack .

Cuando o una tabla sin columnas o , puede forzar el formato de tabla a o con la optión de tabla . Esto hace que las columnas y sean para formato , o para formato .

Puede comprimir o descomprimir tablas especificando con . Consulte Sección 13.1.5, “Sintaxis de .

14.1.3.1. Características de tablas estáticas (con ancho fijo o Fixed-Length)

El formato por defecto para es el estático. Se usa cuando la tabla no contiene columnas de longitud variable (, , o ). Cada registro se almacena usando un número de bytes fijo.

De los tres formatos de almacenamiento , el formato estático es el más simple y seguro (menos sujeto a corrupción). También es el más rápido de los formatos sobre disco. La velocidad proviene de la facilidad con que se encuentran los registros en el fichero de datos en disco: Cuando se busca un registro basándose en un número de registro en el índice, multiplica el número de registro por la longitud de registro. También , al escanear una tabla, es muy fácil leer un número constante de registro con cada operación de lectura de disco.

La seguridad se evidencia si su máquina falla mientras el servidor MySQL está escribiendo en un fichero de formato fijo. En este caso, myisamchk puede determinar fácilmente dónde comienza cada registro y dónde acaba, así que usualmente puede recuperar todos los registros excepto los parcialmente escritos. Tenga en cuenta que los índices de tabla siempre pueden reconstruirse basados en los registros de datos.

Características generales de tablas de formato estático:

  • Las columnas añaden espacios hasta la anchura de columna. Esto también es cierto para columnas , y creadas antes de MySQL 5.0.3.

  • Muy rápido.

  • Fácil de cachear.

  • Fácil de reconstruir tras un fallo, ya que los registros se localizan en posiciones fijas.

  • La reorganización no es necesaria a no ser que borre un gran número de registros y quiera devolver espacio libre al sistema operativo. Para ello, use o myisamchk -r.

  • Usualmente requiere más espacio de disco que para tablas de formato dinámico.

14.1.3.2. Características de tablas dinámicas

El formato de almacenamiento dinámico se usa si una tabla contiene alguna columna de longitud variable (, , o ), o si la tabla se crea con la opción .

Este formato es un poco más complejo ya que cada columna tiene una cabecera que indica la longitud. Un registro puede acabar en más de una localización cuando es alarga como resultado de una actualización.

Puede usar o myisamchk para defragmentar una tabla. Si tiene columnas de longitud fija a las que accede o cambia frecuentemente en una tabla que también contenga alguna columna de longitud variable, puede ser buena idea mover las columnas de longitud variable a otras tablas para evitar fragmentación.

Características generales de tablas de formato dinámico:

  • Todas las columnas de cadenas de carácteres son dinámicas excepto aquéllas con longitud menor a cuatro.

  • Cada registro viene precedido por un bitmap que indica qué columnas contienen la cadena vacía (para columnas de cadenas) o cero (para columnas numéricas). Tenga en cuenta que esto no incluye columnas que contienen valores . Si una columna de cadena de carácteres tiene una longitud de cero tras eliminar los espacios en blanco finales, o una columna numérica tiene un valor de cero, se marca en el bitmap y no se guarda en disco. Las cadenas no vacías se guardan como un byte de longitud más al de los contenidos de la cadena.

  • Para tablas de longitud fija normalmente se necesita mucho menos espacio de disco.

  • Cada registro usa sólo tanto espacio como necesita. Sin embargo, si un registro crece, se divide en tantos trozos como haga falta, resultando en una fragmentación de registro. Por ejemplo, si actualiza un registro con información que alarga la longitud del registro, el registro se fragmenta. En este caso, puede que tenga que ejecutar o myisamchk -r de vez en cuando para mejorar el rendimiento. Use myisamchk -ei para obtener estadísticas de tabla.

  • Más difícil de reconstruir tras un fallo que las tablas de formato estático, ya que los registros pueden fragmentarse en varios trozos y puede faltar algún enlace (fragmento).

  • La longitud de registro esperada para registros de longitud dinámica se calcula usando la siguiente expresión:

    3
    + ( + 7) / 8
    + ()
    + ()
    + ()
    + ( + 7) / 8
    

    Hay una penalización de 6 bytes para cada enlace. Un registro dinámico se enlaza si una actualización provoca aumentar el tamaño de un registro. Cada nuevo enlace es al menos de 20 bytes, así que la siguiente ampliación probablemente irá en el mismo enlace. Si no es así, se crea otro enlace. Puede encontrar el número de enlaces usando myisamchk -ed. Pueden eliminarse todos los enlaces con myisamchk -r.

14.1.3.3. Características de las tablas comprimidas

El formato de almacenamiento comprimido es de sólo lectura generado con la herramienta myisampack.

Todas las distribuciones MySQL incluyen por defecto myisampack. Los escaneos de tablas comprimidas son descomprimidas por myisamchk.

Las tablas comprimidas tienen las siguientes características:

  • Las tablas comprimidas ocupan muy poco espacio. Esto minimiza el uso de disco, lo que es útil al usar discos lentos (como CD-ROMs).

  • Cada registros se comprime por separado, así que hay poca sobrecarga de acceso. La cabecera de un registro ocupa de 1 a 3 bytes en función del registro más grande en la tabla. Cada columna está comprimida de forma distinta. Usualmente hay una árbol de Huffman para cada columna. Algunos de los tipos de compresión son:

    • Compresión espacial de sufijo.

    • Compresión espacial de prefijo.

    • Números con valor de cero se almacenan usando un bit.

    • Si los valores de una columna entara tienen un rango pequeño, la columna se almacena usando el tipo menor posible. Por ejemplo, una columna (ocho bytes) puede almacenarse como columna (un byte) si todos los valores están en el rango de a .

    • Si una columna tiene sólo un pequeño conjunto de valores posibles, el tipo de columna se convierte a .

    • Una columna puede usar cualquier combinación de los tipos de compresión precedentes.

  • Pueden tratar registros de longitud fija o variable.

14.1.4. Problemas en tablas MyISAM

El formato de fichero que usa MySQL para almacenar datos se ha probado extensivamente, pero siempre hay circunstancias que pueden hacer que las tablas se corrompan.

14.1.4.1. Tablas corruptas

Incluso el formato de tabla es muy fiable (todos los cambios hechos en una tabla por un comando SQL se escriben antes que retorne el comando), puede obtener tablas corruptas si cualquiera de los siguientes eventos ocurre:

  • El proceso mysqld muere durante una escritura.

  • La máquina se apaga inesperadamente.

  • Fallos de hardware.

  • Usa un programa externo (como myisamchk) en una tabla que está siendo modificada por el servidor a la vez.

  • Un bug en el código de MySQL o .

Los síntomas típicos de una tabla corrupta son:

  • Obtiene el siguiente error al seleccionar datos de una tabla:

    Incorrect key file for table: '...'. Try to repair it
    
  • Las consultas no obtienen registros en la tabla o retornan datos incompletos.

Puede chequear la salud de una tabla usando el comando , y reparar una tabla corrupta con . Cuando mysqld no está en ejecución, puede chequear o reparar una tabla con el comando myisamchk . Consulte Sección 13.5.2.3, “Sintaxis de , Sección 13.5.2.6, “Sintaxis de , and Sección 5.8.3.1, “Sintaxis para invocar myisamchk.

Si sus tablas se corrompen frecuentemente, debe tratar de determinar porqué ocurre. Lo más importante es saber si la tabla se corrompe como resultado de un fallo de servidor. Puede verificarlo fácilmente buscando un mensaje reciente en el log de errores. Si encuentra dicho mensaje, es probable que la corrupción de tabla sea resultado de la caída del servidor. De otro modo, la corrupción pudo haber ocurrido durante operaciones normales. Esto es un bug. Debe tratar de crear un caso de test reproducible que demuestre el problema. Consulte Sección A.4.2, “Qué hacer si MySQL sigue fallando (crashing)” y Sección D.1.6, “Crear un caso de prueba tras haber encontrado una tabla corrupta”.

14.1.4.2. Problemas debidos a tablas que no se han cerrado debidamente

Cada fichero índice () tiene un contador en la cabecera que puede usarse para chequear si una tabla se ha cerrado correctamente. Si obtiene la siguiente advertencia de o myisamchk, significa que el contador se ha desincronizado:

clients are using or haven't closed the table properly

Esta advertencia no significa necesariamente que la tabla esté corrupta, pero al menos debe chequear la tabla.

El contador funciona como se muesta:

  • La primera vez que se actualiza la hora de una tabla en MySQL, se incrementa un contador en la cabecera del fichero índice.

  • El contador no cambia durante otras actualizaciones.

  • Cuando se cierra la última instancia de una tabla (debido a una operación o porque no hay espacio en la caché de la tabla), el contador se decrementa si la tabla se ha actualizado en cualquier punto.

  • Cuando repara la tabla o chequea la tabla y está correcta, el contador se resetea a cero.

  • Para evitar problemas con interacciones con otros procesos que pueden chequear la tabla, el contador no se decrementea al cerrar si era cero.

En otras palabras, el contador puede desincronizarse sólo bajo las siguientes condiciones:

  • Las tablas se copian sin ejecutar en primer lugar y .

  • MySQL falla entre una actualización y el cierre final. (Tenga en cuenta que la tabla puede estar ok, ya que MySQL siempre realiza escrituras entre cada comando.)

  • Una tabla se modifica con myisamchk --recover o myisamchk --update-state a la vez que se usa con mysqld.

  • Usando múltiples servidores mysqld usando la tabla y un servidor realiza un o en la tabla mientras estaba en uso por otro servidor. En este caso, se puede usar , aunque puede obtener una advertencia de otros servidores. Sin embargo, debe evitarse ya que cuando un servidor reemplaza el fichero de datos con uno nuevo, no se envía a los otros servidores.

    En general, no es buena idea compartir un directorio de datos entre varios servidores. Consulte Sección 5.11, “Ejecutar más de un servidor MySQL en la misma máquina” para más informaicón.