web-dev-qa-db-fra.com

Essayer de résoudre les "limites de l'espace de table extérieures" Erreur MySQL, mais la récupération de table avec MySqldump échoue

J'exécute MySQL sur un serveur Windows 2008. L'une des tables (> 1 million d'enregistrements) semble être corrompue. Le journal d'erreur MySQL montre ceci:

InnoDB: Error: trying to access page number 197105 in space 89,
InnoDB: space name dbname/tablename,
InnoDB: which is outside the tablespace bounds.
InnoDB: Byte offset 0, len 16384, i/o type 10.
InnoDB: If you get this error at mysqld startup, please check that
InnoDB: your my.cnf matches the ibdata files that you have in the
InnoDB: MySQL server.

Basé sur ce message d'erreur, j'ai vérifié my.cnf pour les lignes correspondantes:

innodb_data_home_dir = "C:/xampp/mysql/data"
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = "C:/xampp/mysql/data"

C'est exactement là où les données résident. ibdata1 est d'environ 208 Mo de taille, le nom Tablename.ibd est à propos de 4 Go de taille. J'utilise ce serveur avec succès depuis plusieurs mois.

Après avoir cherché sur ce site et ailleurs, j'ai essayé d'effectuer la récupération comme suit:

  • Régler innodb_force_recovery=1 Et puis jusqu'à 6.
  • Ensuite, vider la table spécifique avec MySqldump. J'utilise cette commande: mysqldump dbname tablename --user=root --password=blahblah. Au cours de cette décharge, pour les niveaux de récupération 1 à 3, MySQL se bloque ("disparaît"). À 4 ans, il a réussi à vider les 23992 records, mais ensuite, il a dit

    Connexion perdue au serveur MySQL lors de la requête lorsque la table de dumping tablename à la ligne: 23992.

    Le journal a quelques lignes supplémentaires précédant ce que j'ai montré ci-dessus:

    InnoDB: Failed to find tablespace for table "dbname"."tablename" in the cache. Attempting to load the tablespace with space id 89. InnoDB: Error: trying to access page number 0 in space 89, InnoDB: space name dbname/tablename, InnoDB: which is outside the tablespace bounds.

  • Il semble que je touche ou (sélectionner) interroger cette table, via PHP, python ou phpmyadmin, MySQL se bloque.

Quelqu'un a-t-il d'autres suggestions, éventuellement sur la base de l'erreur limites des pas de table Erreur ci-dessus?

Merci d'avance!

6
Erjen

Élaborer le message d'erreur

INNODB: ERREUR: Essayer d'accéder à la page Numéro de page 197105 dans l'espace 89,

InnoDB appelle un fichier .ibd un "espace de table" ou juste "espace" dans ce message d'erreur. Donc, il y a un espace 89 et une de ses pages fait référence à un numéro de page non existant 197105. Le message d'erreur ne dit pas quel tableau correspond à l'espace 89. Je pense qu'une version mysql indique que, mais il est possible de trouver du dictionnaire InnoDb.

mysql> select NAME from information_schema.INNODB_SYS_TABLESPACES WHERE SPACE=4304;
+----------------------+
| NAME                 |
+----------------------+
| sakila/film_category |
+----------------------+
1 row in set (0.01 sec)

Maintenant, comme nous savons quel tableau est corrompu la question est de savoir comment le réparer. InnoDB ne guérit pas les espaces de table (comme Myisam le fait avec REPAIR TABLE), la seule façon est de laisser tomber l'espace de la table (= table) et de le reconstituer.

Dans ce cas particulier, il n'est pas nécessaire de démarrer MySQL dans innodb_force_recovery mode. Il suffit de commencer normalement et déposez la table. Mais d'abord, vous devez probablement enregistrer les données dans ce tableau.

Il y a deux manières. Premièrement, vous pouvez choisir des gammes de valeurs de clé primaire non corrompues et de les jeter dans une autre table ou un dépotoir de texte. J'ai eu des cas de récupération comme celui-ci et écrivit un script à faire cela . Le script itière sur le PK varie et décharge autant d'enregistrements que possible dans une autre table (myisam).

La deuxième manière nécessite plus de temps et de compétences. Vous aurez besoin d'un outil ( https://github.com/twindb/undrop-for-innodb ) et un article de blog https://twindb.com/recover-corrupt-mysql -database / avec étapes.

Déposez ensuite la table corrompue, créez-en un vide et chargez le dépotoir récupéré.

1
akuzminsky