web-dev-qa-db-fra.com

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

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_table Pendant le processus. J'ai donc mis innodb_file_per_table Dans 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.ibd Fait 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 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
26
Petr Pudlák

FAITS

Vous avez dit que vous utilisez ext4. La taille maximale des fichiers est de 16 To. Par conséquent, Sample.ibd Ne doit pas être plein.

Vous avez dit que votre innodb_data_file_path Est 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". Cet état complet de la table 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ù émanerait le message Table is Full? 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 quand 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 de restaurer 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 refaire le journal 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 journal de rétablissement peut être trouvé 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. Dans une autre perspective, tous les journaux d'annulation 1023 peuvent être dédiés à la seule transaction qui charge la table Sample.

MAIS ATTENDEZ...

Vous dites probablement "Je charge une table Sample vide". Comment les journaux d'annulation sont-ils impliqués? Avant que la table Sample 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 dans 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 table Sample, veuillez utiliser - no-autocommit

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

Cela mettra un COMMIT; Explicite 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 (a.k.a 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 ibdata2 Est passé à 2196875759616, ce qui correspond à 2145386484M.

J'ai dû incorporer la taille de fichier de ibdata2 Dans innodb_data_file_path et ajouter ibdata3

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, ibdata3 Est passé à 31G. MySQL fonctionnait à nouveau.

33
RolandoMySQLDBA

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 basse pour votre innodb_data_file_path dans ton my.cnf fichier 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 de 512MB des données de toutes les tables InnoDB combinées.

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

3
Joomler