`ERREUR 1114 (HY000) la table… est pleine` avec innodb_file_per_table réglé sur autoextend

26

J'ai une base de données MySQL qui contient une grande quantité de données (100-200 Go - un tas de mesures scientifiques). La grande majorité des données est stockée dans une table Sample. Maintenant, je crée une réplique esclave de la base de données et je voulais profiter des avantages de innodb_file_per_tablependant le processus. J'ai donc mis innodb_file_per_tabledans ma configuration esclave et importé le vidage de la base de données. À ma grande surprise, il a échoué avec

ERREUR 1114 (HY000) à la ligne 5602: le tableau «Échantillon» est plein

Le fichier Sample.ibdfait actuellement environ 93 Go, avec plus de 600 Go d'espace disponible sur la partition, ce n'est donc pas un problème d'espace libre sur le disque. Il ne semble pas non plus atteindre de limite de système de fichiers (j'utilise ext4).

Je serais reconnaissant pour toute idée de ce qui pourrait être la cause, ou sur quoi enquêter.


Mise à jour: j'utilise mysql Ver 14.14 Distrib 5.1.66, for debian-linux-gnu (x86_64).

SELECT @@datadir; -- returns `/home/var/lib/mysql/`
SHOW VARIABLES LIKE '%innodb_data_file_path%'; -- ibdata1:10M:autoextend 

df -h /home/var/lib/mysql/
768G   31G  699G   5% /home
Petr Pudlák
la source

Réponses:

33

LES FAITS

Vous avez dit que vous utilisiez ext4. La taille maximale des fichiers est de 16 To. Ainsi, Sample.ibdne devrait pas être plein.

Vous avez dit que votre innodb_data_file_pathest - ibdata1:10M:autoextend. Ainsi, le fichier ibdata1 lui-même n'a pas de limite à sa taille, sauf à partir du système d'exploitation.

Pourquoi ce message apparaît-il? Notez que le message est "La table ... est pleine", pas "Le disque ... est plein". Cette table pleine condition est d'un point de vue logique . Pensez à InnoDB. Quelles interactions se produisent?

Je suppose qu'InnoDB tente de charger 93 Go de données en une seule transaction. D'où Table is Fullémanerait le message? Je regarderais l'ibdata1, non pas en termes de taille physique (ce que vous avez déjà exclu), mais en termes de limites de transaction atteintes.

Que contient ibdata1 lorsque innodb_file_per_table est activé et que vous chargez de nouvelles données dans MySQL?

  • Dictionnaire de données
  • Tampon d'écriture double
    • Un filet de sécurité pour prévenir la corruption des données
    • Aide à contourner le système d'exploitation pour la mise en cache
  • Insérer un tampon (rationalise les modifications apportées aux index secondaires)
  • Segments de restauration
  • Annuler les journaux
  • Cliquez ici pour voir une représentation picturale de ibdata1

Mes soupçons me disent que les journaux d'annulation et / ou de rétablissement sont à blâmer.

Quels sont ces journaux? Selon le livre

sxs

Chapitre 10: «Moteurs de stockage» Page 203 Les paragraphes 3,4 indiquent ce qui suit:

Le moteur InnoDB conserve deux types de journaux: un journal d'annulation et un journal de rétablissement. Le but d'un journal d'annulation est d' annuler les transactions, ainsi que d'afficher les anciennes versions des données pour les requêtes exécutées au niveau d'isolement des transactions qui le nécessite. Le code qui gère le journal d'annulation peut être trouvé dans storage / innobase / buf / log / log0log.c .

Le but du journal de rétablissement est de stocker les informations à utiliser dans la récupération après incident. Il permet au processus de récupération de réexécuter les transactions qui peuvent ou non se terminer avant le crash. Après avoir réexécuté ces transactions, la base de données est amenée à un état cohérent. Le code traitant du fichier de journalisation se trouve dans storage / innobase / log / log0recv.c .

UNE ANALYSE

Il y a 1023 journaux d' annulation dans ibdata1 (voir Segments de restauration et espace d'annulation) . Étant donné que les journaux d'annulation conservent des copies des données telles qu'elles apparaissaient avant le rechargement, tous les 1023 journaux d'annulation ont atteint leur limite. D'un autre point de vue, tous les journaux d'annulation 1023 peuvent être dédiés à la seule transaction qui charge la Sampletable.

MAIS ATTENDEZ...

Vous dites probablement "Je charge une Sampletable vide ". Comment les journaux d'annulation sont-ils impliqués? Avant que la Sampletable ne soit chargée avec 93 Go de données, elle était vide. La représentation de chaque ligne qui n'existait pas doit occuper un espace de nettoyage dans les journaux d'annulation. Remplir 1023 journaux d'annulation semble insignifiant étant donné la quantité de données versées ibdata1. Je ne suis pas la première personne à soupçonner cela:

Dans la documentation MySQL 4.1, notez Posted by Chris Calender on September 4 2009 4:25pm:

Notez que dans 5.0 (avant 5.0.85) et dans 5.1 (avant 5.1.38), vous pourriez recevoir l'erreur "table est pleine" pour une table InnoDB si InnoDB manque de slots d'annulation (bug # 18828).

Voici le rapport de bogue pour MySQL 5.0: http://bugs.mysql.com/bug.php?id=18828

SUGGESTIONS

Lorsque vous créez le mysqldump de la Sampletable, veuillez utiliser --no-autocommit

mysqldump --no-autocommit ... mydb Sample > Sample.sql

Cela mettra un explicite COMMIT;après chaque INSERT. Ensuite, rechargez la table.

Si cela ne fonctionne pas ( vous n'aimerez pas ça ), faites ceci

mysqldump --no-autocommit --skip-extended-insert ... mydb Sample > Sample.sql

Ainsi, chaque INSERT n'aura qu'une seule ligne. Le mysqldump sera beaucoup plus grand (10 fois plus grand) et pourrait recharger 10 à 100 fois plus longtemps.

Dans les deux cas, cela évitera que les journaux d'annulation soient inondés.

Essaie !!!

MISE À JOUR 2013-06-03 13:05 EDT

SUGGESTION SUPPLÉMENTAIRE

Si la table système InnoDB (alias ibdata1) atteint une limite de taille de fichier et que les journaux d'annulation ne peuvent pas être utilisés, vous pouvez simplement ajouter un autre espace disque logique système (ibdata2).

Je viens de rencontrer cette situation il y a à peine deux jours. J'ai mis à jour mon ancien article avec ce que j'ai fait: Voir Conception de base de données - Création de plusieurs bases de données pour éviter le mal de tête de limiter la taille de la table

En substance, vous devez modifier innodb_data_file_path pour accueillir un nouveau fichier d'espace disque logique système. Permettez-moi d'expliquer comment:

SCÉNARIO

Sur le disque (ext3), le serveur de mon client avait les éléments suivants:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  2 00:15 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  2 00:15 ibdata2

Le cadre était

innodb_data_file_path=ibdata1:346M;ibdata2:500M:autoextend:max:10240000M

Notez que ibdata2ce chiffre est passé à 2196875759616 2145386484M.

J'ai dû intégrer la taille du fichier ibdata2dans innodb_data_file_path et ajouteribdata3

innodb_data_file_path=ibdata1:346M;ibdata2:2196875759616;ibdata3:10M:autoextend

Lorsque j'ai redémarré mysqld, cela a fonctionné:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  3 17:02 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  3 17:02 ibdata2
-rw-rw---- 1 s-em7-mysql s-em7-mysql   32315015168 Jun  3 17:02 ibdata3

En 40 heures, est ibdata3passé à 31G. MySQL fonctionnait à nouveau.

RolandoMySQLDBA
la source
Je suppose que par le nom du propriétaire, votre client utilisait un outil de surveillance à venir ... Merci, cela semble également avoir résolu un problème pour moi.
Steve
Je me demande si c'est toujours un problème (j'espère que non)
Evan Carroll
3

J'ai eu le même problème et je viens de faire une chose et cela a fonctionné.

Vous semblez avoir une taille maximale trop faible pour votre innodb_data_file_pathdans votre my.cnffichier de configuration. Modifiez simplement le code ci-dessous -

innodb_data_file_path = ibdata1:10M:autoextend:max:512M

Remarque importante Vous ne pouvez pas héberger plus 512MBde données dans toutes les InnoDB tables combinées.

Vous pouvez également basculer vers un schéma innodb par table à l'aide de innodb_file_per_table.

Joomler
la source