J'ai un site Web très fréquenté où il est possible que des milliers de nouveaux enregistrements soient insérés toutes les heures.
Cette seule erreur paralyse le site:
PDOException: SQLSTATE[40001]: Serialization failure: 1213
Deadlock found when trying to get lock;
try restarting transaction: INSERT INTO {location_instance}
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4);
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] =>
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] =>
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )
Je serais très surpris si MySQL ne pouvait pas gérer ce type de charge. Donc, mes questions sont alors, est-ce un problème de base de données et comment puis-je configurer MySQL pour pouvoir gérer autant de trafic?
J'ai une copie de mon site Web installée sur un serveur de développement avec des scripts qui simulent la charge de contenu ajoutée au site Web. J'utilise Ubuntu, pile LAMP, avec 16 Go de RAM.
Certes, je ne connais pas très bien les bases de données. En fait, je commence avec le fichier my.cnf par défaut qui l'accompagne après la fin de «apt-get install». Les tables sont toutes Innodb. Quels paramètres de configuration et quelle approche recommanderiez-vous pour commencer à résoudre ce problème?
Faites-moi savoir de plus amples informations dont vous pourriez avoir besoin.
Merci
Réponses:
Vous avez affaire à un blocage, pas à un problème de goulot d'étranglement des performances.
Si vous avez un millier de nouveaux enregistrements par heure, vous êtes loin de pouvoir atteindre les limites de MySQL. MySQL peut gérer au moins 50 fois votre charge.
Les interblocages sont dus au code d'application et ne sont pas la faute du serveur de base de données. Les blocages ne peuvent pas être corrigés côté serveur MySQL, sauf dans certaines situations spécifiques.
InnoDB
peut vous montrer des informations détaillées sur les blocages en exécutantSHOW ENGINE INNODB STATUS
à l'invite MySQL ou avecmysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
.Cependant, cela ne montre que le dernier blocage qui s'est produit, il n'y a pas de journal de blocage.
Heureusement, il existe un outil pt-deadlock-logger qui s'occupe de ce problème, il prend en charge l'état d'interrogation
InnoDB
et enregistre toutes les informations détaillées sur les interblocages avant qu'il ne soit actualisé avec un nouveau blocage.la source
Cela peut être aussi simple qu'une partie de votre code exécutant une transaction:
tandis qu'une autre partie de votre code modifie les mêmes tables dans un ordre différent:
Si ces deux transactions s'exécutent en même temps, une condition de concurrence critique peut se produire: la première transaction ne peut pas être modifiée
t2
car elle est verrouillée par la deuxième transaction; tandis que la deuxième transaction est également bloquée car ellet1
est verrouillée par la première transaction. MySQL choisit une transaction pour être la "victime" où INSERT / UPDATE / DELETE échoue. L'application doit intercepter cette erreur et réessayer l'instruction - peut-être après une pause pour que l'autre transaction ait le temps de se terminer. Rien à voir avec les limites de capacité, juste un timing malheureux qui peut être exacerbé par la façon dont le code est organisé. Basculez les DELETEs dans la transaction # 2 ou les INSERTs dans la transaction # 1, puis il n'y a pas de conflit - chaque transaction attendra l'accès aux tables dont elle a besoin.Dans MySQL 5.6, vous pouvez exécuter avec l' option innodb_print_all_deadlocks activée pour collecter des informations sur tous les blocages (pas seulement le plus récent) dans le journal des erreurs MySQL.
[Clause de non-responsabilité obligatoire: je suis un employé d'Oracle. Ce qui précède est mon avis personnel et non une déclaration officielle.]
la source