web-dev-qa-db-fra.com

Quel est le risque de garder une table avec la taille de la ligne> 8126 dans MySQL 5.7?

Je viens de passer à partir de MySQL 5.6 à 5.7 et j'ai eu la mauvaise surprise de découvrir que A WordPress contient des champs 438 ridicules et dépasse la limite de taille de la ligne de 8126 octets.

Voici l'avertissement que j'ai eu lors de la course mysql_upgrade:

Taille de la rangée trop grande (> 8126). Changer certaines colonnes en texte ou blob ou en utilisant Row_Format = Dynamic ou Row_Format = compressé peut aider. Dans le format de ligne actuel, le préfixe BLOB de 768 octets est stocké en ligne.

C'était juste un avertissement cependant, et la table est toujours là. Je ne peux pas créer une nouvelle table avec la même structure , mais assez intéressante, Je peux garder l'ancienne table et utilisez-le (au moins, SELECT de celui-ci).

J'ai lu Rolandomysqldba's et Bill Karwin's réponses sur des sujets similaires et aucune solution ne peut m'aider:

  • changer de ROW_FORMAT=DYNAMIC ne suffit pas, car la table est pleine d'inline UTF-8 VARCHAR champs qui seules dépassent la taille maximale
  • la modification de la structure de la table est hors de question, car elle fait partie d'un logiciel tiers, et ce serait comme ouvrir une boîte de vers

J'ai signalé l'erreur des développeurs du plugin et j'espère qu'ils répareront la table bientôt, mais entre-temps, je suis coincé avec cette table hors al.

Les questions sont donc:

  • Comment MySQL fonctionne-t-il avec une table qui ne respecte pas les règles de stockage InnoDB, lorsqu'elle ne permet pas de créer une telle table?
  • Y a-t-il un risque de garder la table dans son état actuel?
  • Existe-t-il des limitations sur le type de requêtes que je peux courir sur cette table?
  • Si je reproduit ce serveur à un autre serveur MySQL 5.7, la réplication échouera-t-elle à cause de cette table?

J'ai mis à jour de MySQL 5.6. J'ai essayé DYNAMIC et COMPRESSED formats, mais pas de chance. J'ai calculé la taille des champs entier + Varchar, ils totalisent 17 059 octets. Je n'ai donc aucune chance de réussir de cette façon.

Le plugin est appelé Galerie de photos et la table défectueuse est wp_bwg_theme.

5
Benjamin
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=ON;
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- Or COMPRESSED

C'est ce qui était nécessaire en 5.6, je pense. Depuis Barracuda et File_Per_Table sont des valeurs par défaut de 5,7, la plupart de cela s'en vont. Cependant, la mise à niveau peut avoir laissé la table antilope et/ou non file_per_table.

Donc, je recommande de lancer ces 3 commandes et de voir si elle "corrige" votre problème pour le bien. (Ouais, gardez une sorte de sauvegarde quelque part d'abord.)

Vous avez mentionné UTF8; Peut-être que vous voulez utf8mb4 aussi?

ALTER TABLE tbl CONVERT TO utf8mb4;

(Je ne sais pas maintenant si la réplication sera un problème. Vraisemblablement après les modifications ci-dessus, ce ne sera pas un problème sur un esclave 5.7.)

modifier

Mais ... étant la valeur par défaut (pour 5,7) non signifie que vous avez ces valeurs pour un existant fichier après une mise à niveau.

Regarder dans information_schema.INNODB_SYS_TABLES Pour voir ce que le file_format et row_format sommes. La colonne space indique File_Per_Table si la valeur est> 0.

Un moyen drastique de faire face au problème: Changez la taille de la page InnoDB. La valeur par défaut est de 16 kb, mais 32kb est possible. Si je ne me trompe pas, Tous Tables sur le système doivent être converties à la nouvelle taille de la page, il s'agit donc d'une entreprise non triviale et peut avoir d'autres ramifications.

la manipulation de VARCHAR in DYNAMIC/COMPRESSED

Quand la chaîne est-elle stockée dans la partie principale de l'enregistrement, versus stockée dans un autre bloc?

  • Petite taille (la chaîne est <40 octets): la chaîne entière est stockée avec l'enregistrement. 2 + n octets.
  • Taille moyenne: "petit" ou "grand", selon "enregistrement pas trop gros".
  • Grande taille: 2 + 20 octets en enregistrement (longueur + pointeur); Texte total stocké séparément.

"Enregistrez trop gros": lorsque la ligne est trop longue, les colonnes les plus longues sont stockées dans le stockage hors page. C'est-à-dire, parfois une colonne sera entièrement hors page, parfois à la page, en fonction du maquillage de la ligne entière.

VARCHAR et TEXT et BLOB sont traités les mêmes pour DYNAMIC ou COMPRESSED.

Le format DYNAMIC est basé sur l'idée que si une partie d'une valeur de données longue est stockée hors page, il est généralement plus efficace de stocker toute la valeur hors page ("tout ou aucune").

COMPRESSED = DYNAMIC + compression. KEY_BLOCK_SIZE contrôle la quantité de données de colonnes stockées dans l'indice en cluster et la quantité de pages de débordement.

5.7 référence et plus vieux, plus détaillé, discussion ; et d'autres pages.

2
Rick James

Après avoir lu Rick James 'réponse (+1 pour lui) , la seule chose que j'ajouterais pour celui-ci est juste de configurer un plus grand piscine de tampon InnoDb si vous allez avec ROW_FORMAT=COMPRESSED. Pourquoi ?

J'avais mentionné dans mon ancien post innodb_file_format barracuda Comment augmenter la taille du pool tampon pour accueillir la décompression des pages que vous accédez.

Plagiaire de mon propre post ...

SCÉNARIO

  • Vous avez un serveur DB avec une piscine tampon de 8g
  • Vous avez couru compression avec key_block_size=8
    • 8 est 50.00% de 16
    • 50.00% de 8G est 4G
    • augmenter innodb_buffer_pool_size à 12G (8G + 4G)
  • Vous avez couru compression avec key_block_size=4
    • 4 est 25.00% de 16
    • 25.00% de 8G est 2G
    • augmenter innodb_buffer_pool_size à 10G (8G + 2G)
  • Vous avez couru compression avec key_block_size=2
    • 2 est 12.50% de 16
    • 12.50% de 8G est 1G
    • augmenter innodb_buffer_pool_size à 9G (8G + 1G)
  • Vous avez couru compression avec key_block_size=1
    • 1 est 06.25% de 16
    • 06.25% de 8G est 0.5G (512M)
    • augmenter innodb_buffer_pool_size à 8704M (8G (8192M) + 512M)

Morale de l'histoire : Le pool de tampons Innodb a besoin d'une salle de respiration supplémentaire lors de la manipulation de données et de pages d'index compressées.

1
RolandoMySQLDBA