Réparer une base mariadb "Tablespace is missing for a table" from storage engine InnoDB

Salut,
Même si c’est arrivé sur une simple debian, je note ça ici au cas où ça arrive sur un yunohost, ça aidera peut être quelqu’un…

Contexte

Une personne m’a contacté suite à une mésaventure lié à une coupure de courant. Elle n’avait pas de backup récent. Elle a fait plusieurs opérations pour relancer mysql (je ne sais pas lesquelles), puis a bloqué sur ce message qui apparaît si on essaie de lire une table:

ERROR 1030 (HY000): Got error 194 "Tablespace is missing for a table" from storage engine InnoDB
# lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

# dpkg -l | grep mariadb-server
ii  mariadb-server                       1:10.3.34-0+deb10u1                                                        all          MariaDB database server (metapackage depending on the latest version)
rc  mariadb-server-10.1                  10.1.41-0+deb9u1                                                           amd64        MariaDB database server binaries
ii  mariadb-server-10.3                  1:10.3.34-0+deb10u1                                                        amd64        MariaDB database server binaries
ii  mariadb-server-core-10.3             1:10.3.34-0+deb10u1                                                        amd64        MariaDB database core server files

1. Utiliser l’outil dbsake pour reconstruire les CREATE TABLE

db=nextcloud
sudo -u mysql ./dbsake frmdump -r -R /var/lib/mysql/$db/ > $db-create.sql

2. Retirer les index:

tr '\n' ' ' < $db-create-nokey.sql | sed "s/, )/)/g" > $db-create-nokey2.sql
sed "s/;/;\n/g" $db-create-nokey2.sql | sed "s/,/,\n/"g | sed "s/ -- / -- \n/g" > $db-create-nokey3.sql

3. Faire un fichier pour ajouter plus tard les index:

grep -E "(-- Table| (UNIQUE )?KEY)" $db-create.sql | sed "s/-- Table structure for table /ALTER TABLE /g" | sed "s/ KEY/ ADD KEY/g" | sed "s/ UNIQUE KEY/ ADD UNIQUE KEY/g" | sed "s/)$/);/g" > $db.key.sql

(il faut enlever manuellement les ALTER TABLE isolé)

4.Faire une copie des fichiers brut de la BDD

cp -a /var/lib/mysql/$db /root/$db

5. Supprimer les fichier ibd

rm /var/lib/mysql/$db/*.ibd

6. Recréer les base de donnée

mysql -u USER -p $db -e "DROP DATABASE $db; CREATE DATABASE $db;"

mysql -u USER -p $db < $db-create-nokey3.sql

7. Discard, copier le ibd puis import

mysql -u USER -p $db -e "SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' DISCARD TABLESPACE;') AS _ddl FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='$db' AND ENGINE='InnoDB';" > discard-$db.sql
mysql -u USER -p $db -e "SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' IMPORT TABLESPACE;') AS _ddl FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='$db' AND ENGINE='InnoDB';" > import-$db.sql

mysql -v -u USER -p $db < discard-$db.sql
cp -a /root/$db/*.ibd /var/lib/mysql/$db/
mysql -v -u USER -p $db < import-$db.sql

8. Si il y a des erreurs Schema mismatch

“ERROR 1808 (HY000): Schema mismatch (Expected FSP_SPACE_FLAGS=0x21, .ibd file contains 0x0.)”, modifier la création de la table dans $db-create-nokey3.sql en ajoutant ROW_FORMAT=compact, et recommencer à partir de l’étape 5**

9. Charger les clés

mysql -v -u USER -p $db < $db.key.sql

Conclusion

N’attendez pas pour mettre en place un backup cette fois…

mysqldump -u USER -p $db > /root/$db.sql
2 Likes