Un article ici sur DBA.StackExchange ( Quelles sont les meilleures pratiques pour les déclencheurs pour maintenir un numéro de révision sur les enregistrements? ) A suscité une question intéressante (au moins, intéressante pour moi) concernant les performances dans MySQL.
Le contexte est que nous voulons insérer un enregistrement dans une table pour chaque ligne mise à jour. Avant la mise à jour de la ligne, nous voulons stocker une valeur précédente, puis incrémenter une des colonnes (une colonne "version").
Si nous le faisons à l'intérieur d'un déclencheur, cela fonctionne bien. Pour MySQL, les déclencheurs sont ligne par ligne , donc ce serait une solution facile. Sélectionnez les données actuellement dans la table, insérez-les dans la table de journalisation et mettez à jour la colonne "version" dans les nouvelles données.
Cependant, il est possible de déplacer cette logique vers une procédure stockée. Si vous faites cela, vous effectuez l'insertion, puis incrémentez la colonne "version" dans le tableau. Le tout serait réglé en fonction.
Donc, quand il s'agit de réaliser cet insert, cela serait-il plus performant d'utiliser l'approche de procédure stockée basée sur un ensemble ou une approche basée sur un déclencheur?
Cette question est pour MySQL (car il a des déclencheurs ligne par ligne), bien qu'elle puisse s'appliquer à d'autres SGBD de déclenchement ligne par ligne.
Réponses:
Dans un souci de simplicité, les déclencheurs sont la voie à suivre pour implémenter tout type de suivi des modifications de la base de données. Cependant, vous devez être conscient de ce qui se passe sous le capot lorsque vous utilisez des déclencheurs.
Selon MySQL Stored Procedure Programming , la page 256 sous la rubrique "Trigger Overhead" dit ce qui suit:
Une explication détaillée de la surcharge de déclenchement est donnée aux pages 529-531. Le point de conclusion de cette section indique ce qui suit:
Non mentionné dans le livre est un autre facteur lors de l'utilisation de déclencheurs: en ce qui concerne la journalisation d'audit, veuillez être conscient de ce dans quoi vous vous connectez. Je dis cela parce que si vous choisissez de vous connecter à une table MyISAM, chaque INSERT dans une table MyISAM produit un verrou de table complet pendant l'insertion. Cela peut devenir un goulot d'étranglement sérieux dans un environnement à trafic élevé et à transactions élevées. De plus, si le déclencheur est contre une table InnoDB et que vous enregistrez les modifications dans MyISAM à partir du déclencheur, cela désactivera secrètement la conformité ACID (c'est-à-dire, réduira les transactions de bloc au comportement de validation automatique), qui ne peut pas être annulée.
Lors de l'utilisation de déclencheurs sur des tables InnoDB et des modifications de journalisation
De cette façon, les journaux d'audit peuvent bénéficier de COMMIT / ROLLBACK comme les tables principales.
En ce qui concerne l'utilisation des procédures stockées, vous devrez appeler minutieusement la procédure stockée à chaque point de DML par rapport à la table en cours de suivi. On pourrait facilement manquer des changements de journalisation face à des dizaines de milliers de lignes de code d'application. Placer un tel code dans un déclencheur élimine la recherche de toutes ces instructions DML.
CAVEAT
Selon la complexité du déclencheur, il peut toujours s'agir d'un goulot d'étranglement. Si vous souhaitez réduire les goulots d'étranglement dans la journalisation d'audit, vous pouvez faire quelque chose. Cependant, cela nécessitera un petit changement d'infrastructure.
En utilisant du matériel standard, créez deux autres serveurs DB
Cela servira à réduire les E / S d'écriture sur la base de données principale (MD) en raison de la journalisation d'audit. Voici comment vous pouvez y parvenir:
Étape 01) Activez la journalisation binaire dans la base de données principale.
Étape 02) À l'aide d'un serveur peu coûteux, configurez MySQL (même version que MD) avec la journalisation binaire activée. Ce sera DM. Configurez la réplication de MD vers DM.
Étape 03) À l'aide d'un deuxième serveur peu coûteux, configurez MySQL (même version que MD) avec la journalisation binaire désactivée. Configurez chaque table d'audit pour utiliser --replicate-do-table . Ce sera AU. Configurez la réplication de DM vers AU.
Étape 04) mysqldump les structures de table de MD et chargez-les dans DM et AU.
Étape 05) Convertissez toutes les tables d'audit dans MD pour utiliser le moteur de stockage BLACKHOLE
Étape 06) Convertissez toutes les tables en DM et AU pour utiliser le moteur de stockage BLACKHOLE
Étape 07) Convertissez toutes les tables d'audit en AU pour utiliser le moteur de stockage MyISAM
Lorsque vous avez terminé
Cela permet de stocker les informations d'audit sur un serveur de base de données distinct et de réduire également toute dégradation des E / S d'écriture que MD aurait normalement.
la source
Voici une approche pour effectuer cette mise à jour en masse.
Pour cet exemple
Pour créer table_A_Keys2Update, procédez comme suit:
Après avoir rempli table_A_Keys2Update avec les identifiants dont le numéro de révision doit être incrémenté, effectuez la mise à jour UPDATE JOIN suivante pour incrémenter le numéro de révision de toutes les lignes dont l'ID se trouve à la fois dans table_A et table_A_Keys2Update:
Cette requête d'une ligne peut remplacer un déclencheur et une procédure stockée.
Facultativement, vous pouvez placer cette seule requête dans une procédure stockée et l'appeler si vous le souhaitez.
la source