ACTUALIZACIÓN: tl; dr: El problema era que MySQL usa el TMPDIR
al crear índices. Y mi TMPDIR
fue el que se estaba quedando sin espacio en disco.
Q original:
Estoy tratando de agregar un índice a una tabla InnoDB y obtengo un table is full error
. Tengo suficiente espacio en disco y la configuración de MySQL tiene un archivo por tabla = 1. Los datos de la tabla son de 85 GB y supongo que el índice será de alrededor de 20 GB a 30 GB y tengo mucho más espacio en disco que eso. También estoy usando ext3, así que no creo que haya ningún problema con el límite de tamaño de archivo desde el punto de vista del sistema operativo.
El error registrado se ve así:
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
¿Qué está causando esto y cómo puedo resolverlo?
La tabla de creación:
`CREATE TABLE `my_table` (
`uid_from` bigint(11) NOT NULL,
`uid_to` bigint(11) NOT NULL,
`counter` int(11) NOT NULL,
`updated` date NOT NULL,
PRIMARY KEY (`uid_to`,`uid_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8`
Como es, los datos son 87.4GB y calculo que hay alrededor de 1.5B filas.
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Variable_name Value
tmpdir /tmp
[root@web ~]# df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 40G 24G 14G 64% /
Respuestas:
No se deje engañar por el mensaje de error
The table 'my_table' is full
. Este raro escenario no tiene absolutamente nada que ver con el espacio en disco. Esta condición completa de la tabla tiene que ver con la fontanería interna de InnoDB.Primero, eche un vistazo a este diagrama de la arquitectura InnoDB
Tenga en cuenta que el espacio de tabla del sistema (el archivo ibdata) solo tiene 128 segmentos de reversión y 1023 ranuras de reversión por segmento de reversión. Esto pone límites al tamaño de la capacidad de reversión de una transacción. En otras palabras, si un solo segmento de reversión necesita más de 1023 ranuras para admitir una transacción, la transacción alcanzará esa
table is full
condición.Piense en el restaurante Red Lobster en Nueva Jersey . Puede tener una capacidad de 200 personas. Si el restaurante está lleno, una fila de personas puede salir a esperar. Si las personas en la fila se impacientan, pueden irse porque el restaurante está lleno. Obviamente, la solución no sería hacer que Nueva Jersey sea más grande (u obtener más espacio en disco). La solución sería agrandar el restaurante Red Lobster. De esa manera, puede aumentar la capacidad de asientos a, digamos, 240. Incluso con eso, se puede formar una fila afuera si más de 240 personas deciden venir a Red Lobster.
Solo para darle un ejemplo, tenía un cliente con 2TB de espacio de tabla del sistema y se deshabilitó innodb_file_per_table . (346G para ibdata1, el restablecimiento para ibdata2). Ejecuté esta consulta
Luego, resté InnoDBDataIndexSpace de la suma de los tamaños de archivo para ibdata1 e ibdata2. Tengo dos cosas que me sorprendieron
Table is Full
condiciónEsto significa que el 106GB estaba utilizando para la fontanería interna de InnoDB. El cliente estaba usando ext3 en ese momento.
La solución para mí fue agregar ibdata3. Discutí esto en mi publicación anterior ¿Cómo resolver "La tabla ... está llena" con "innodb_file_per_table"?
He discutido esto en otras publicaciones también
Mar 31, 2014
: el directorio mysql crece a 246G después de una consulta, que falló debido a que la tabla está llenaNov 25, 2011
: ERROR 1114 (HY000) en la línea 6308 en el archivo y la tabla user_analysis está llenaTenga en cuenta que esta condición puede ocurrir incluso si innodb_file_per_table estaba habilitado. ¿Cómo? Los retrocesos y los registros de deshacer son la fuente de picos incontrolados, es el crecimiento de ibdata1 .
TU PREGUNTA REAL
Como está agregando un índice a una tabla y obteniendo
Table is Full
, la tabla debe ser enorme y no puede caber dentro de un solo segmento de reversión. Debes hacer lo siguiente:PASO 01
Obtener los datos en un archivo de volcado
PASO 02
Inicie sesión en MySQL y ejecute esto
PASO 03
Cargue la tabla con el índice adicional con los datos.
Eso es todo.
Vea, el problema es que ALTER TABLE intentará inyectar todas las filas en su tabla enorme como una sola transacción. El uso de mysqldump insertará los datos en la tabla (ahora con un nuevo índice) miles de filas a la vez, no todas las filas en una sola transacción.
No se preocupe por
what if this doesn't work?
la tabla original se nombrarámytable_old
en caso de cualquier cosa. Puede servir como respaldo. Puede soltar la copia de seguridad cuando sepa que la nueva tabla funciona para usted.Darle una oportunidad !!!
ACTUALIZACIÓN 2014-06-16 11:13 EDT
Si le preocupa el volcado de los datos más grandes, simplemente gzip.
Puedes hacer los mismos pasos, pero de la siguiente manera
PASO 01
Obtener los datos en un archivo de volcado
PASO 02
Inicie sesión en MySQL y ejecute esto
PASO 03
Cargue la tabla con el índice adicional con los datos.
o
ACTUALIZACIÓN 2014-06-16 12:55 EDT
Acabo de pensar en otro aspecto con respecto a este tema.
Como está haciendo DDL y no DML, es posible que esto no sea una tubería interna de InnoDB. Dado que DDL no puede revertir para InnoDB , el problema tiene que ser la plomería externa. ¿Dónde se está obstruyendo esta tubería externa? Sospecho que la carpeta temporal para el sistema operativo. ¿Por qué?
¿Ves el
disk quota exceeded
? ¿Dónde se impone esta cuota de disco?Ejecute esta consulta
Dijiste que es
/var/lib/mysqltmp
Ahora, ejecuta esto en el sistema operativo
Algo me dice que el espacio se
/var/lib/mysqltmp
estaba acabando Después de todo, solo tienes 14G gratis. A los ojos del DDL (para crear el índice), ocurrió una reversión, no en el archivo ibdata1, sino en latmpdir
ubicación. Si/var/lib/mysqltmp
no está montado en ningún lugar, los datos temporales se escriben en la partición raíz. Si/var/lib/mysqltmp
está montado en algún lugar, entonces ese montaje se está llenando con datos de fila. En cualquier caso, no hay suficiente espacio para completar el DDL.Tienes dos opciones aquí
OPCIÓN 1
También puede crear un disco grande (quizás con más de 100 GB) y montarlo
/var/lib/mysqltmp
en ese disco grande.OPCION 2
Mis sugerencias de 3 pasos aún deberían funcionar, incluso con el espacio en disco limitado que tiene
COMENTARIO
Es una pena que el mensaje de error que publicaste dice
Esto significa que el sistema operativo está bien. Tampoco existe ningún número de error asociado para esta situación.
Hay otra cosa que debes saber. La documentación de MySQL dice que la creación rápida de índices para InnoDB todavía va al disco :
ACTUALIZACIÓN 2014-06-16 13:58 EDT
Asegúrate de que
/mnt/cbsvolume1/var/lib/mysql
tenga 100G o más gratisfuente