Comment puis-je changer la limite
Taille de ligne trop grande (> 8126). Changer certaines colonnes en TEXT ou BLOB ou utiliser ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED
peut aider. Dans le format de ligne actuel, le préfixe BLOB
de 768 octets est stocké en ligne.
Table:
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
La question a également été posée sur serverfault .
Vous voudrez peut-être jeter un oeil à cet article qui explique beaucoup de choses sur la taille des lignes MySQL. Il est important de noter que même si vous utilisez Dans les champs TEXT ou BLOB, la taille de votre ligne peut toujours être supérieure à 8 Ko (limite pour InnoDB), car elle stocke les 768 premiers octets de chaque champ inséré dans la page.
Le moyen le plus simple de résoudre ce problème consiste à utiliser le format de fichier Barracuda avec InnoDB. Cela élimine fondamentalement le problème en stocker uniquement le pointeur de 20 octets sur les données de texte au lieu de stocker les 768 premiers octets.
La méthode qui a fonctionné pour le PO il y avait:
Ajoutez les éléments suivants au fichier my.cnf
dans la section [mysqld]
.
innodb_file_per_table=1
innodb_file_format = Barracuda
ALTER
la table à utiliser ROW_FORMAT=COMPRESSED
.
ALTER TABLE nombre_tabla
ENGINE=InnoDB
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8;
Il est possible que ce qui précède ne résout toujours pas vos problèmes. Il s'agit d'un bogue connu (et vérifié) avec le moteur InnoDB, et une solution temporaire consiste à utiliser le moteur MyISAM comme mémoire de stockage temporaire. Donc, dans votre fichier my.cnf
:
internal_tmp_disk_storage_engine=MyISAM
J'ai rencontré ce problème récemment et l'ai résolu d'une manière différente. Si vous utilisez la version 5.6.20 de MySQL, il existe un bogue connu dans le système. Voir Documentation MySQL
Important En raison du bogue n ° 69477, les écritures de journal de reprise pour les grands champs BLOB stockés en externe pourraient écraser le plus. point de contrôle récent. Pour résoudre ce problème, un correctif introduit dans MySQL 5.6.20 limite la taille de redo log BLOB écrit à 10% de la taille du fichier de journalisation. En conséquence de cette limite, innodb_log_file_size doit être défini sur une valeur supérieure à 10 fois la plus grande taille de données BLOB trouvée dans les lignes de votre fichier tables plus la longueur des autres champs de longueur variable (champs de type VARCHAR, VARBINARY et TEXT).
Dans mon cas, la table blob incriminée était d'environ 16MB. Ainsi, la façon dont j'ai résolu le problème consistait à ajouter une ligne à my.cnf qui garantissait que j'avais au moins 10 fois ce montant, puis:
innodb_log_file_size = 256M
Si vous pouvez changer de moteur et utiliser MyISAM au lieu d’InnoDB, cela devrait aider:
ENGINE=MyISAM
Il y a deux mises en garde avec MyISAM (sans doute plus):
Je voudrais partager une réponse géniale, cela pourrait être utile. Crédits Bill Karwin voir ici https://dba.stackexchange.com/questions/6598/innodb-create-table-error-row-size-too-large
Ils varient selon le format de fichier InnoDB. Il existe actuellement deux formats appelés Antelope et Barracuda.
Le fichier de tablespace central (ibdata1) est toujours au format Antelope. Si vous utilisez fichier par table, vous pouvez obliger chaque fichier à utiliser le format Barracuda en définissant innodb_file_format = Barracuda dans my.cnf.
Points de base:
Une page de données InnoDB de 16 Ko doit contenir au moins deux lignes de données. De plus, chaque page comporte un en-tête et un pied de page contenant les sommes de contrôle de page, le numéro de séquence du journal, etc. C'est là que vous obtenez votre limite d'un peu moins de 8 Ko par ligne.
Les types de données de taille fixe tels que INTEGER, DATE, FLOAT, CHAR sont stockés sur cette page de données primaire et sont comptabilisés dans la limite de taille de ligne.
Les types de données de taille variable tels que VARCHAR, TEXT, BLOB sont stockés sur les pages de débordement. Par conséquent, ils ne comptent pas entièrement dans la limite de taille de ligne. Dans Antelope, jusqu’à 768 octets de telles colonnes sont stockés sur la page de données principale en plus de ceux stockés sur la page de dépassement. Barracuda prend en charge un format de ligne dynamique, de sorte qu'il ne peut stocker qu'un pointeur de 20 octets sur la page de données primaire.
Les types de données de taille variable sont également préfixés avec un ou plusieurs octets pour coder la longueur. Et le format de ligne InnoDB comporte également un tableau de décalages de champs. Il existe donc une structure interne plus ou moins documentée dans leur wiki.
Barracuda prend également en charge ROW_FORMAT = COMPRESSED pour optimiser l’efficacité du stockage en cas de débordement de données.
Je dois également dire que je n’ai jamais vu une table bien conçue dépasser la limite de taille de lignes. C'est une "odeur de code" forte que vous violez la condition de groupes répétitifs de la première forme normale.
Définissez les éléments suivants sur votre fichier my.cnf et redémarrez le serveur mysql.
innodb_strict_mode = 0
J'ai eu le même problème, cela l'a résolu pour moi:
ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;
De MYSQL Documentation :
Le format de ligne DYNAMIC maintient l'efficacité du stockage de l'intégralité du fichier rangée dans le noeud d’index si cela convient (comme le font les formats COMPACT et REDUNDANT ), mais ce nouveau format évite le problème du remplissage du b-arbre. nœuds avec un grand nombre d'octets de données de longues colonnes. La dynamique Le format est basé sur l’idée que si une partie d’une valeur de données longue est stocké hors page, il est généralement plus efficace de stocker tous les fichiers valeur hors page. Avec le format DYNAMIC, les colonnes plus courtes sont susceptibles de rester dans le nœud B-tree, minimisant le nombre de pages de débordement nécessaire pour une ligne donnée.
Après avoir passé des heures, j'ai trouvé la solution: il suffit d'exécuter le code suivant dans votre administrateur MySQL pour convertir la table en MyISAM:
USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;
J'ai aussi rencontré le même problème. Je résous le problème en exécutant le SQL suivant:
ALTER ${table} ROW_FORMAT=COMPRESSED;
Mais, je pense que vous devriez savoir à propos de Row Storage .
Il existe deux types de colonnes: colonne de longueur variable (type VARCHAR, VARBINARY, BLOB et TEXT) et colonne de longueur fixe. Ils sont stockés dans différents types de pages.
Les colonnes de longueur variable constituent une exception à cette règle. Les colonnes telles que BLOB et VARCHAR qui sont trop longues pour tenir sur une page B-tree sont stockées sur des pages de disque allouées séparément, appelées pages de débordement. Nous appelons ces colonnes des colonnes hors page. Les valeurs de ces colonnes sont stockées dans des listes de pages de débordement à liaison unique, chacune de ces colonnes ayant sa propre liste d'une ou de plusieurs pages de débordement. Dans certains cas, la totalité ou un préfixe de la valeur de colonne longue est stocké dans le B-tree, pour éviter de gaspiller de la mémoire et éliminer le besoin de lire une page séparée.
et lorsque le but de définir ROW_FORMAT est
Lorsqu'une table est créée avec ROW_FORMAT = DYNAMIC ou ROW_FORMAT = COMPRESSED, InnoDB peut stocker des valeurs de colonne de longueur variable longues (pour les types VARCHAR, VARBINARY, BLOB et TEXT) entièrement hors page, avec l'enregistrement d'index cluster contenant seulement 20 point d’octet sur la page de débordement.
En savoir plus sur Formats de rangée DYNAMIC et COMPRESSED
Les autres réponses répondent à la question posée. Je vais aborder la cause sous-jacente: mauvaise conception du schéma.
Ne pas afficher un tableau sur plusieurs colonnes. Ici vous avez 3 * 10 colonnes qui doivent être transformées en 10 lignes de 3 colonnes dans une nouvelle table (plus id
, etc.)
Votre table Main
aurait seulement
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
Votre table supplémentaire (Top
) aurait
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
Il y aurait 10 rangées (ou moins? Ou plus?) Dans Top
pour chaque id
.
Cela élimine votre problème d'origine et nettoie le schéma. (Ce n'est pas une "normalisation", comme cela a été débattu dans certains commentaires.)
Do not basculez sur MyISAM; ça s'en va.
Ne vous inquiétez pas pour ROW_FORMAT
.
Vous devrez modifier votre code pour utiliser la variable JOIN
et gérer plusieurs lignes au lieu de plusieurs colonnes.
Si cela se produit sur un SELECT comportant plusieurs colonnes, la cause peut en être que mysql crée une table temporaire. Si ce tableau est trop volumineux pour tenir en mémoire, il utilisera son format de tableau temporaire par défaut, InnoDB, pour le stocker sur le disque. Dans ce cas, les limites de taille InnoDB s'appliquent.
Vous avez alors 4 options:
changez le format de table temporaire par défaut en MYISAM, c'est ce que j'ai fait. Changement dans my.cnf:
internal_tmp_disk_storage_engine=MYISAM
Redémarrez mysql, la requête fonctionne.
J'ai rencontré ce problème lorsque j'essayais de restaurer une base de données mysql sauvegardée à partir d'un autre serveur. Ce qui a résolu ce problème pour moi, c’est d’ajouter certains paramètres à my.conf (comme dans les questions ci-dessus) et de modifier en outre le fichier de sauvegarde SQL:
Étape 1: Ajoutez ou modifiez les lignes suivantes dans my.conf:
innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1
Étape 2 ajoutez ROW_FORMAT = DYNAMIC à la déclaration de création de table dans le fichier de sauvegarde SQL de la table à l'origine de cette erreur:
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;
le changement important ci-dessus est ROW_FORMAT = DYNAMIC; (qui n'était pas inclus dans le fichier de sauvegarde SQL original)
source qui m'a aidé à résoudre ce problème: MariaDB et InnoDB MySQL Taille de la ligne trop grande