Pourquoi les tables MySQL plantent-elles? Comment puis-je l'empêcher?

9

Je suis l'administrateur d'un site Moodle dont la table Users a été corrompue et qui est devenue inutilisable.

Heureusement, un simple a REPAIR TABLE mdl_userfait fonctionner à nouveau. Le fait est que je ne sais pas pourquoi il s'est réellement écrasé et l'a rendu inutilisable, et je veux m'assurer que je suis mieux préparé la prochaine fois.

Je ne suis pas un DBA très expérimenté - je suis juste un développeur qui fait beaucoup de choses, alors soyez indulgents

Je pourrais simplement restaurer une sauvegarde, mais je suppose qu'il existe des moyens de prévenir les plantages.

Ces tables sont utf8_general_ci et utilisent MyISAM.

Pourquoi une table MySQL plante-elle? Que puis-je faire pour empêcher que cela se produise?

AeroCross
la source

Réponses:

11

Il est assez facile de planter une table MyISAM.

Dans l'en-tête de chaque table MyISAM se trouve un compteur qui suit le nombre de descripteurs de fichiers ouverts par rapport à la table.

Si vous démarrez mysql et que le nombre dans l'en-tête ne correspond pas au nombre de descripteurs de fichiers réels, mysqld traite la table comme plantée.

Si un simple le REPAIR TABLE mdl_userfait fonctionner à nouveau à chaque fois sans perte de données, cela peut indiquer que vous avez un site très fréquenté qui écrit mdl_user.

Si des dizaines de tables l'exigent REPAIR TABLE, je convertirais toutes les tables en InnoDB. Cependant, si la mdl_usertable est la seule table avec ce problème, vous pouvez faire quelque chose (pour cet exemple, disons que la base de données l'est moodle);

Si vous voulez que toutes les tables restent MyISAM

ÉTAPE 01: créer un script de table de réparation

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

ÉTAPE 02: Déclarez le script de réparation comme fichier de démarrage

Ajoutez ceci à /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

ÉTAPE 03: Redémarrez mysql

Chaque redémarrage de mysql déclenchera le script de table de réparation

Si vous voulez que toutes les tables deviennent InnoDB

Exécutez ce code pour créer un script de conversion en masse des tables MyISAM vers InnoDB et affichez-le

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

Une fois que vous êtes satisfait du contenu du script de conversion, exécutez-le

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

MISE À JOUR 2012-03-15 14:00 EDT

@Kevin , lors de l'utilisation de MyISAM, que se passe-t-il si vous manquez d'espace disque?

Voici quelque chose à considérer: selon le guide d'étude de certification MySQL 5.0 ,

entrez la description de l'image ici

La puce n ° 11 indique ce qui suit aux pages 408 et 409, section 29.2:

Si vous manquez d'espace disque lors de l'ajout de lignes à une table MyISAM, aucune erreur ne se produit. Le serveur suspend l'opération jusqu'à ce que de l'espace soit disponible, puis termine l'opération.

Lorsque vous manquez d'espace disque, ne vous contentez pas d'arrêter ou de tuer mysql. Le nombre de descripteurs de fichiers ouverts dans tout MyISAM actuellement utilisé n'aura pas été effacé. Ainsi, la table MyISAM est marquée comme plantée. Si vous pouvez libérer de l'espace disque dans le volume de données avec mysqld toujours en cours d'exécution, mysqld se poursuivra une fois que l'espace disque sera disponible.

RolandoMySQLDBA
la source
Excellente réponse. Je ne connaissais pas le bit des poignées de fichier, et vous avez déjà résolu comment puis-je empêcher (ou réparer automatiquement) en cas de problème. Une suggestion de sécurité si le site fait en fait beaucoup d'écritures sur mdl_user (ou toute autre table)?
AeroCross
Vous devriez faire trois choses: 1) augmenter la RAM, 2) augmenter les max_connections, 3) passer à InnoDB.
RolandoMySQLDBA
Noob ici. Où dois-je "exécuter" ce code? À partir d'un fichier téléchargé sur le serveur ou d'une ligne de commande?
UncaughtTypeError
0

J'administre également un site moodle sur mysql, et la cause la plus courante de corruption de table pour nous est de manquer d'espace disque.

Kevin
la source
@RolandoMySQLDBA - oui, l'espace disque est certainement le problème (lié à d'autres processus et à la philosophie de gestion en général). Malheureusement, nous ne voyons pas le problème se résoudre lui-même lorsque l'espace est dégagé, ou il ne se résout pas lui-même en temps opportun. Ma réponse était juste de souligner qu'avec notre instance moodle / mysql, les problèmes d'espace disque peuvent provoquer des plantages de table, indépendamment de ce que mysql / myisam est censé faire.
Kevin
-3

J'ai trouvé une bonne ligne pour convertir toutes les tables en InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName
Dmitry
la source
Le code peut être correct pour cela mais il ne répond pas à la première question (pourquoi une table MySQL plante-t-elle?). Si vous voulez dire qu'il répond à la deuxième partie (Comment l'empêcher?), Ajoutez quelques explications supplémentaires, s'il vous plaît.
ypercubeᵀᴹ
Ajoutez également plus de détails. Est-ce que l'exécution de cela convertira toutes les tables d'une base de données? Ou tout le serveur? Que se passera-t-il si une table ne parvient pas à se convertir et que nous obtenons une erreur? Est-il possible que nous nous retrouvions avec des tables converties et d'autres laissées dans MyiSAM? En général, quelles autres choses un DBA doit-il considérer avant d'exécuter cela?
ypercubeᵀᴹ