Erreur de taille de ligne avec MySQL

11

J'utilise un serveur MySQL sur mon Macbook (pour les tests). La version est 5.6.20 de Homebrew. J'ai commencé à rencontrer des erreurs de «taille de ligne trop grande» et j'ai pu la réduire à ce cas de test. Table:

mysql> describe test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| stuff | longtext | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+

Statut de la table:

mysql> show table status where Name = 'test';
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| test | InnoDB |      10 | Compact    |    1 |          16384 |       16384 |               0 |            0 |   5242880 |              2 | 2014-08-28 23:51:12 | NULL        | NULL       | utf8_general_ci |     NULL |                |         |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+

L'erreur stuffque j'obtiens lorsque j'essaie d'insérer une ligne dans la table où la colonne a plus de 5033932 octets.

mysql> select length(stuff) from test;
+---------------+
| length(stuff) |
+---------------+
|       5033932 |
+---------------+

mysql> update test set stuff = concat(stuff, 'a');
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

J'ai cherché cette erreur, la plupart des réponses impliquent d'avoir trop de colonnes TEXT, et chacune a 768 octets stockés en ligne. Comme vous pouvez le voir, ce n'est pas le cas pour moi. En outre, le nombre 5033932 reste le même quel que soit le nombre de colonnes que j'ai dans le tableau. Dans mon application d'origine, il y avait cinq colonnes et les mises à jour ont toujours échoué lorsque la taille de la colonne dépassait 5033932.

J'ai également vu des gens résoudre le problème en changeant de format de ligne, ce que j'essaierai un peu, mais je voudrais comprendre exactement ce qui cause cette erreur.

Merci d'avance!

geoffliu
la source

Réponses:

12

Un changement dans les notes de version 5.6.20:

Les écritures de journalisation pour les grands champs BLOB stockés en externe pourraient remplacer le point de contrôle le plus récent. Le correctif 5.6.20 limite la taille des écritures de journalisation BLOB à 10% de la taille du fichier de journalisation. Le patch 5.7.5 corrige le bogue sans imposer de limitation. Pour MySQL 5.5, le bogue reste une limitation connue.

En raison de la limite d'écriture BLOB de rétablissement du journal introduite pour MySQL 5.6, 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 vos tables, plus la longueur des autres champs de longueur variable (VARCHAR, VARBINARY et champs de type TEXTE). Ne pas le faire pourrait entraîner des erreurs «Taille de ligne trop grande».

(c'est moi qui souligne)

La valeur par défaut innodb_log_file_sizeest 50331648, ce qui signifie que la plus grande valeur BLOB / TEXT que vous pouvez créer, quel que soit le type de données, est proche de 5033164, et vous avez découvert que la valeur précise est 5033932. Je suppose qu'en interne, le calcul implique un facteur de fudge.

Vous devez donc augmenter innodb_log_file_sizesi vous souhaitez stocker des données BLOB / TEXT plus volumineuses. Heureusement, la modification de la taille du fichier journal est beaucoup plus facile dans 5.6 que dans les versions antérieures d'InnoDB. Ajoutez simplement une ligne dans votre my.cnf avec la nouvelle valeur et redémarrez mysqld.

Bill Karwin
la source
petite remarque, vous devez redémarrer ou arrêter et recommencer pour que le changement soit affecté, le rechargement ne fonctionne pas
Hieu Vo
1
Cette limite de taille de rétablissement est assouplie à 10% du total combiné innodb_log_file_size (innodb_log_file_size * innodb_log_files_in_group) de mysql 5.6.22. Et le longblob peut avoir une longueur maximale de 4294967295 (2 ^ 32 - 1) caractères, soit 4 Go environ. Pour stocker cette valeur longblob, nous devons avoir au moins 40 Go combinés innodb_log_file_size (innodb_log_file_size * innodb_log_files_in_group).
kasi