Cambiar el límite para "El tamaño de la fila de Mysql es demasiado grande"

104

¿Cómo puedo cambiar el límite?

El tamaño de la fila es demasiado grande (> 8126). Cambiar algunas columnas a TEXT o BLOB o usar ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSEDpuede ayudar. En el formato de fila actual, el BLOBprefijo de 768 bytes se almacena en línea.

Mesa:

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
top_a   varchar(255)    No       
top_b   varchar(255)    No       
top_c   varchar(255)    No       
top_d   varchar(255)    No       
top_e   varchar(255)    No       
top_f   varchar(255)    No       
top_g   varchar(255)    No       
top_h   varchar(255)    No       
top_i   varchar(255)    No       
top_j   varchar(255)    No       
top_title_a varchar(255)    No       
top_title_b varchar(255)    No       
top_title_c varchar(255)    No       
top_title_d varchar(255)    No       
top_title_e varchar(255)    No       
top_title_f varchar(255)    No       
top_title_g varchar(255)    No       
top_title_h varchar(255)    No       
top_title_i varchar(255)    No       
top_title_j varchar(255)    No       
top_desc_a  text    No       
top_desc_b  text    No       
top_desc_c  text    No       
top_desc_d  text    No       
top_desc_e  text    No       
top_desc_f  text    No       
top_desc_g  text    No       
top_desc_h  text    No       
top_desc_i  text    No       
top_desc_j  text    No       
status  int(11) No       
admin_id    int(11) No 
Lasha Kurt
fuente
1
¿Qué se Nomuestra?
hjpotter92
No se puede actualizar el error "El tamaño de la fila es demasiado grande (> 8126). Cambiar algunas columnas a TEXT o BLOB o usar ROW_FORMAT = DYNAMIC o ROW_FORMAT = COMPRESSED puede ayudar. En el formato de fila actual, el prefijo BLOB de 768 bytes se almacena en línea".
Lasha Kurt
¿Puedes agregar algunos otros detalles a tu publicación, al menos como comentario?
Eineki
1
Si estos datos están en otra tabla, considere usar una clave externa en su lugar, esto disminuirá drásticamente el tamaño de su fila y normalizará el esquema de su base de datos.
didierc
1
@AL: Vaya, tienes razón, vota de cerca por el otro
pathikrit

Respuestas:

121

La pregunta también se ha hecho sobre la falla del servidor .

Es posible que desee echar un vistazo a este artículo que explica mucho sobre los tamaños de fila de MySQL. Es importante tener en cuenta que incluso si usa campos de TEXTO o BLOB, el tamaño de su fila aún podría ser superior a 8K (límite para InnoDB) porque almacena los primeros 768 bytes para cada campo en línea en la página.

La forma más sencilla de solucionar este problema es utilizar el formato de archivo Barracuda con InnoDB. Básicamente, esto elimina el problema por completo al almacenar solo el puntero de 20 bytes a los datos de texto en lugar de almacenar los primeros 768 bytes.


El método que funcionó para el OP fue:

  1. Agregue lo siguiente al my.cnfarchivo en la [mysqld]sección.

    innodb_file_per_table=1
    innodb_file_format = Barracuda
  2. ALTERla mesa a utilizar ROW_FORMAT=COMPRESSED.

    ALTER TABLE nombre_tabla
        ENGINE=InnoDB
        ROW_FORMAT=COMPRESSED 
        KEY_BLOCK_SIZE=8;

Existe la posibilidad de que lo anterior aún no resuelva sus problemas. Es un error conocido (y verificado) con el motor InnoDB , y una solución temporal por ahora es recurrir al motor MyISAM como almacenamiento temporal. Entonces, en su my.cnfarchivo:

internal_tmp_disk_storage_engine=MyISAM
hjpotter92
fuente
12
+1 -> La parte innodb_file_per_table es crucial y va de la mano con el cambio de formato a Barracuda. Sin él, MySQL seguirá usando silenciosamente Antelope.
Nick
1
@Eduardo Recomendaría hacer una copia de seguridad de los datos primero. Pero sí, ¡también puedes hacer esto en producción!
hjpotter92
3
Use innodb_file_per_table=1para activar esta opción.
Stijn Geukens
2
No se garantiza que esto solucione el problema. Consulte esta publicación para ver un script de ejemplo que agrega estas configuraciones pero aún puede reproducir el error.
Cerin
1
@ user1183352 Actualicé mi respuesta anterior. Gracias por recordarme de nuevo que profundice en esto. :)
hjpotter92
61

Me encontré con este problema recientemente y lo resolví de una manera diferente. Si está ejecutando MySQL versión 5.6.20, hay un error conocido en el sistema. Ver documentos de MySQL

Importante Debido al error # 69477, las escrituras de registro de rehacer para campos BLOB grandes almacenados externamente podrían sobrescribir el punto de control más reciente. Para solucionar este error, un parche introducido en MySQL 5.6.20 limita el tamaño de las escrituras de BLOB del registro de rehacer al 10% del tamaño del archivo de registro de rehacer. Como resultado de este límite, innodb_log_file_size debe establecerse en un valor mayor que 10 veces el tamaño de datos BLOB más grande que se encuentra en las filas de sus tablas más la longitud de otros campos de longitud variable (campos de tipo VARCHAR, VARBINARY y TEXT).

En mi situación, la tabla de blobs ofensiva era de alrededor de 16 MB. Por lo tanto, la forma en que lo resolví fue agregando una línea a my.cnf que aseguraba que tuviera al menos 10 veces esa cantidad y algo más:

innodb_log_file_size = 256M

Colin
fuente
Correcto. Mi error "Tamaño de fila demasiado grande" en un longblobcampo desapareció tan pronto como aumenté el innodb_log_file_sizeparámetro. También se estaba ejecutando 5.6.20.
Adamup
Gracias. Estaba ejecutando homebrew 5.6.21, cambiar el parámetro solucionó el problema.
nanoman
Tanto esta como la respuesta de @ hjpotter92 fueron necesarias para corregir este error.
Cerin
Gracias. Se estaba ejecutando 5.6.21 y esta solución ayudó.
petiar
Esto tampoco resolvió mi problema. Estoy considerando reemplazar muchos de mis campos VARCHAR por TEXT, como he visto en hilos similares.
PDoria
28

Configure lo siguiente en su archivo my.cnf y reinicie el servidor mysql.

innodb_strict_mode=0
Karl
fuente
2
innodb_strict_mode=0-> sin espacios. De lo contrario, reiniciar mariaDB 10.2 da como resultado un error :-P
Pathros
No probé con mariadb, para MySQL no es necesario eliminar espacios.
Karl
1
De acuerdo con la documentación, deshabilitar el modo estricto solo evita que aparezcan errores y advertencias, por lo que no parece resolver el problema. download.nust.na/pub6/mysql/doc/innodb-plugin/1.1/en/…
João Teixeira
2
Esto parece funcionar y me permite crear las tablas sin problemas y almacenar datos
Chris Muench
@ João, hace más .. dev.mysql.com/doc/refman/8.0/en/…
Karl
24

Si puede cambiar el MOTOR y usar MyISAM en lugar de InnoDB, eso debería ayudar:

ENGINE=MyISAM

Hay dos advertencias con MyISAM (posiblemente más):

  1. No puede utilizar transacciones.
  2. No puede usar restricciones de clave externa.
fénix
fuente
5
Está bien si no le importa ir sin transacciones y restricciones de clave externa. Pero tenga en cuenta que los pierde al cambiar a MyISAM.
wobbily_col
Este consejo es una locura, ¡al menos fíjate que hará todas las advertencias! ¡Las transacciones y las restricciones de clave foregith son el menor de los problemas con este formato!
Hassan Syed
Lo siento, voté en contra de esta respuesta. Actualice para mencionar todas las advertencias involucradas. Cualquiera que siga este consejo cambia a un formato que yo nunca usaría en ningún sistema de producción.
Remco Wendt
2
Y MyISAM se va.
Rick James
2
trabajó para mi. Mi caso tenía más de 300 campos de aproximadamente 10 de longitud cada uno. No tengo ninguna relación en esta tabla, por lo que cambiar a MyISAM fue la solución.
Robert Saylor
12

Me gustaría compartir una respuesta increíble, podría ser útil. Créditos Bill Karwin ver aquí /dba/6598/innodb-create-table-error-row-size-too-large

Varían según el formato de archivo InnoDB. En la actualidad existen 2 formatos llamados Antelope y Barracuda.

El archivo de espacio de tabla central (ibdata1) siempre está en formato Antelope. Si usa archivo por tabla, puede hacer que los archivos individuales usen el formato Barracuda configurando innodb_file_format = Barracuda en my.cnf.

Puntos basicos:

  1. Una página de 16 KB de datos InnoDB debe contener al menos dos filas de datos. Además, cada página tiene un encabezado y un pie de página que contienen sumas de verificación de página y número de secuencia de registro, etc. Ahí es donde obtiene su límite de un poco menos de 8 KB por fila.

  2. Los tipos de datos de tamaño fijo como INTEGER, DATE, FLOAT, CHAR se almacenan en esta página de datos primarios y cuentan para el límite de tamaño de fila.

  3. Los tipos de datos de tamaño variable como VARCHAR, TEXT, BLOB se almacenan en páginas de desbordamiento, por lo que no cuentan completamente para el límite de tamaño de fila. En Antelope, hasta 768 bytes de dichas columnas se almacenan en la página de datos principal además de almacenarse en la página de desbordamiento. Barracuda admite un formato de fila dinámico, por lo que puede almacenar solo un puntero de 20 bytes en la página de datos principal.

  4. Los tipos de datos de tamaño variable también tienen como prefijo 1 o más bytes para codificar la longitud. Y el formato de fila InnoDB también tiene una matriz de compensaciones de campo. Entonces hay una estructura interna más o menos documentada en su wiki.

Barracuda también admite ROW_FORMAT = COMPRESSED para obtener una mayor eficiencia de almacenamiento de datos desbordados.

También debo comentar que nunca he visto una tabla bien diseñada que exceda el límite de tamaño de fila. Es un fuerte "olor a código" que está violando la condición de grupos repetidos de la Primera Forma Normal.

Aman Chhabra
fuente
7

Tuve el mismo problema, esto me lo resolvió:

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;

De la documentación de MYSQL :

El formato de fila DYNAMIC mantiene la eficiencia de almacenar toda la fila en el nodo de índice si cabe (al igual que los formatos COMPACT y REDUNDANT), pero este nuevo formato evita el problema de llenar los nodos del árbol B con una gran cantidad de bytes de datos de columnas largas. El formato DYNAMIC se basa en la idea de que si una parte de un valor de datos largo se almacena fuera de la página, por lo general es más eficiente almacenar todo el valor fuera de la página. Con el formato DYNAMIC, es probable que las columnas más cortas permanezcan en el nodo del árbol B, lo que minimiza el número de páginas de desbordamiento necesarias para una fila determinada.

multimediaxp
fuente
... pero necesitas tener un formato de archivo diferente, ¿así que ya estás en Barracuda? Porque me sale un error al intentar ese comando, diciendoWarnings from last query: InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope
Ted
Cuando dejo que HeidiSQL ejecute el mismo comando a través de su GUI incorporada, de alguna manera tuvo éxito, pero no ayudó en absoluto, obtengo el mismo error,Row size too large (>8126)
Ted
Intente establecer innodb_file_format = Barracuda en my.ini y pruebe ALTER TABLE my_tableROW_FORMAT = DYNAMIC; de nuevo
multimediaxp
Sí, creo que eso es lo que hice al final, y creo que eso lo resolvió. Pero también cambié muchas columnas a TEXTO al mismo tiempo en desesperación =) Aunque, de hecho creo que eso fue todo.
Ted
¡Bien !, si crees que esta es una buena respuesta, dale un voto positivo y acepta como respuesta válida, ¡gracias!
multimediaxp
5

Después de pasar horas, encontré la solución: simplemente ejecute el siguiente SQL en su administrador de MySQL para convertir la tabla a MyISAM:

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;
Iftikhar Khan
fuente
No ayuda mucho si el problema ocurre en una declaración de creación de tabla.
Mark Fraser
create tabletiene la misma opción:CREATE TABLE ... ENGINE=MyISAM ...
xebeche
3

Me encontré con este problema cuando intentaba restaurar una base de datos mysql respaldada desde un servidor diferente. Lo que resolvió este problema para mí fue agregar ciertas configuraciones a my.conf (como en las preguntas anteriores) y, además, cambiar el archivo de respaldo SQL:

Paso 1: agregue o edite las siguientes líneas en my.conf:

innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1

Paso 2 agregue ROW_FORMAT = DYNAMIC a la declaración de creación de tabla en el archivo de respaldo sql para la tabla que está causando este error:

DROP TABLE IF EXISTS `problematic_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `problematic_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
  ...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 ROW_FORMAT=DYNAMIC;

el cambio importante anterior es ROW_FORMAT = DYNAMIC; (que no se incluyó en el archivo de respaldo sql original)

fuente que me ayudó a resolver este problema: MariaDB e InnoDB MySQL Tamaño de fila demasiado grande

matyas
fuente
1
Las líneas descritas en el paso 1 no deben tener ningún espacio. La línea innodb_page_size=32Kno funcionó, ya que provocó un error al reiniciar MariaDB 10.2 en mi caso. En su lugar, agregué una innodb_strict_mode=0línea, como se describe aquí
Pathros
1
gracias por los comentarios Pathros, actualicé mi respuesta y eliminé los espacios del paso 1.
matyas
Nota para MySQL <= 5.7.5: 32K no es una opción válida para innodb_page_size. Ver: dev.mysql.com/doc/refman/5.6/en/…
Dub Nazar
Además, debe volver a crear todo su servidor mysql para scracth, ya que el cambio innodb_page_sizerequiere ibdata*recreación, que es una operación destructiva. Mire su registro del sistema para obtener más información
Matija Nalis
2

Las otras respuestas abordan la pregunta formulada. Abordaré la causa subyacente: un diseño de esquema deficiente.

No extienda una matriz entre columnas. Aquí tiene 3 * 10 columnas que deben convertirse en 10 filas de 3 columnas en una nueva tabla (más id, etc.)

Tu Mainmesa solo tendría

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
status  int(11) No       
admin_id    int(11) No 

Tu mesa extra ( Top) tendría

id  int(11) No          -- for joining to Main
seq TINYINT UNSIGNED    -- containing 1..10
img   varchar(255)    No       
title varchar(255)    No       
desc  text    No    
PRIMARY KEY(id, seq)    -- so you can easily find the 10 top_titles

Habría 10 (¿o menos? ¿O más?) Filas Toppara cadaid .

Esto elimina su problema original y limpia el esquema. (Esto no es "normalización", como se debate en algunos de los Comentarios).

Hacer no cambiar a MyISAM; se va
No se preocupe ROW_FORMAT.

Deberá cambiar su código para hacer el JOINy para manejar múltiples filas en lugar de múltiples columnas.

Rick James
fuente
1

Estoy usando MySQL 5.6 en AWS RDS. Actualicé lo siguiente en el grupo de parámetros.

innodb_file_per_table=1
innodb_file_format = Barracuda

Tuve que reiniciar la instancia de base de datos para que los cambios del grupo de parámetros tuvieran efecto.

Además, ROW_FORMAT = COMPRESSED no fue compatible. Usé DYNAMIC como se muestra a continuación y funcionó bien.

ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8
Mihir Kagrana
fuente
1

El tamaño máximo de fila para una tabla InnoDB, que se aplica a los datos almacenados localmente dentro de una página de base de datos, es un poco menos de media página para 4 KB, 8 KB, 16 KB y 32 KB.

Para páginas de 16 kb (predeterminado), podemos calcular:

Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum

Básicamente, podrías maximizar una fila con:

  • 11 campos varchar> 767 caracteres (latin1 = 1 byte por carácter) o
  • 11 campos varchar> 255 caracteres (utf-8 en mysql = 3 bytes por carácter).

Recuerde, solo se desbordará a una página de desbordamiento si el campo tiene> 767 bytes. Si hay demasiados campos de 767 bytes, se romperá (pasando más allá de max row_size). No es habitual con latin1 pero es muy posible con utf-8 si los desarrolladores no tienen cuidado.

Para este caso, creo que posiblemente podría aumentar el innodb_page_size a 32kb.

en my.cnf:

innodb_page_size=32K

Referencias:

U0001
fuente
0

También encontré el mismo problema. Resuelvo el problema ejecutando el siguiente sql:

ALTER ${table} ROW_FORMAT=COMPRESSED;

Pero, creo que deberías saber sobre Row Storage .
Hay dos tipos de columnas: columna de longitud variable (como los tipos VARCHAR, VARBINARY y BLOB y TEXT) y columna de longitud fija . Se almacenan en diferentes tipos de páginas.

Las columnas de longitud variable son una excepción a esta regla. Las columnas como BLOB y VARCHAR que son demasiado largas para caber en una página de árbol B se almacenan en páginas de disco asignadas por separado llamadas páginas de desbordamiento. Llamamos a estas columnas columnas fuera de la página. Los valores de estas columnas se almacenan en listas de páginas de desbordamiento vinculadas individualmente, y cada columna tiene su propia lista de una o más páginas de desbordamiento. En algunos casos, todo o un prefijo del valor de la columna larga se almacena en el árbol B, para evitar desperdiciar almacenamiento y eliminar la necesidad de leer una página separada.

y cuando el propósito de establecer ROW_FORMAT es

Cuando se crea una tabla con ROW_FORMAT = DYNAMIC o ROW_FORMAT = COMPRESSED, InnoDB puede almacenar valores de columna largos de longitud variable (para los tipos VARCHAR, VARBINARY y BLOB y TEXT) completamente fuera de la página, con el registro de índice agrupado que contiene solo un 20- puntero de byte a la página de desbordamiento.

¿Quieres saber más sobre los formatos de fila DINÁMICO y COMPRIMIDO?

Será
fuente
0

Si esto ocurre en un SELECT con muchas columnas, la causa puede ser que mysql está creando una tabla temporal. Si esta tabla es demasiado grande para caber en la memoria, usará su formato de tabla temporal predeterminado, que es InnoDB, para almacenarla en el disco. En este caso, se aplican los límites de tamaño de InnoDB.

Entonces tienes 4 opciones:

  1. cambie el límite de tamaño de fila de innodb como se indica en otra publicación, lo que requiere la reinicialización del servidor.
  2. cambie su consulta para incluir menos columnas o evite que se cree una tabla temporal (por ejemplo, eliminando las cláusulas de orden y límite).
  3. cambiando max_heap_table_size para que sea grande para que el resultado se ajuste a la memoria y no sea necesario escribirlo en el disco.
  4. cambiar el formato de tabla temporal predeterminado a MYISAM, esto es lo que hice. Cambio en my.cnf:

    internal_tmp_disk_storage_engine=MYISAM

Reinicie mysql, la consulta funciona.

bhelm
fuente
0

Aquí hay un consejo simple para cualquiera que esté interesado:

Después de actualizar de Debian 9 a Debian 10 con 10.3.17-MariaDB, tengo algunos errores de las bases de datos de Joomla:

[Advertencia] InnoDB: No se puede agregar un campo fielden la tabla database.tableporque después de agregarlo, el tamaño de la fila es 8742 que es mayor que el tamaño máximo permitido (8126) para un registro en la página hoja de índice.

Por si acaso, configuré innodb_default_row_format = DYNAMIC en /etc/mysql/mariadb.conf.d/50-server.cnf (de todos modos era predeterminado)

Entonces, he usado phpmyadmin para ejecutar "Optimizar tabla" para todas las tablas en la base de datos de Joomla. Creo que la recreación de la mesa realizada por phpmyadmin en el proceso ayudó. Si tiene phpmyadmin instalado, solo tiene que hacer unos pocos clics.

joomlauser
fuente
Si eres un usuario de Joomla, únete a nosotros en Joomla Stack Exchange; siempre podemos utilizar nuevos colaboradores.
mickmackusa