LES FAITS
Vous avez dit que vous utilisiez ext4
. La taille maximale des fichiers est de 16 To. Ainsi, Sample.ibd
ne devrait 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". 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
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 Sample
table.
MAIS ATTENDEZ...
Vous dites probablement "Je charge une Sample
table vide ". Comment les journaux d'annulation sont-ils impliqués? Avant que la Sample
table 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 Sample
table, 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 ibdata2
ce chiffre est passé à 2196875759616 2145386484M
.
J'ai dû intégrer la taille du fichier ibdata2
dans 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 ibdata3
passé à 31G. MySQL fonctionnait à nouveau.