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
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?
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 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.
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
.
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
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 !!!
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:
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.
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
.