Partage de technologie

Notes d'étude pratiques MySQL 45 conférences (mises à jour continuellement...)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


1. Infrastructure : Comment une instruction de requête SQL est-elle exécutée ?

Aperçu

Insérer la description de l'image ici

D'une manière générale, MySQL peut être divisé en deux couches

  • Couche serveur
    Couvre la plupart des fonctions de base du service MySQL
    • Connecteur
    • Cache de requêtes
    • Analyseur
    • optimiseur
    • Actionneur
    • Toutes les fonctions intégrées (telles que la date, l'heure, les fonctions mathématiques et cryptographiques, etc.)
    • Capacités sur les moteurs de stockage
      • procédure stockée
      • déclenchement
      • voir
      • ……
  • couche de moteur de stockage
    Architecture plug-in, responsable du stockage et de la récupération des données
    • Innodb
    • MonISAM
    • Mémoire

Connecteur

mysql -h$ip -P$port -u$user -p
  • 1

Le mysql dans la commande de connexion est un outil client utilisé pour établir une connexion avec le serveur.Après avoir terminé la négociation TCP classique, le connecteur
Il est sur le point de commencer à authentifier votre identité. À ce moment-là, le nom d'utilisateur et le mot de passe que vous avez saisis seront utilisés.

  • Si le nom d'utilisateur ou le mot de passe est incorrect, vous recevrez une erreur « Accès refusé pour l'utilisateur », puis le programme client
    Terminer l'exécution.
  • Si l'authentification par nom d'utilisateur et mot de passe réussit, le connecteurTableau des autorisations Découvrez les autorisations dont vous disposez là-bas.Ensuite, à ce propos
    La logique de jugement des autorisations dépendra des autorisations lues à ce moment-là.

Insérer la description de l'image ici
Si le client reste inactif trop longtemps, le connecteur le déconnectera automatiquement. Ce temps est contrôlé par le paramètre wait_timeout et la valeur par défaut est de 8 heures.

Si le client envoie à nouveau une requête après la déconnexion de la connexion, il recevra un rappel d'erreur : Lost connection to MySQL server during query . Si vous souhaitez continuer à ce moment-là, vous devez vous reconnecter puis exécuter la requête.

Dans la base de données, une connexion longue signifie qu'une fois la connexion réussie, si le client continue de faire des requêtes, la même connexion sera toujours utilisée. Une connexion courte signifie que la connexion est déconnectée après l'exécution de quelques requêtes et qu'une nouvelle est rétablie pour la requête suivante.

Le processus d'établissement d'une connexion est généralement compliqué, je vous suggère donc d'essayer de minimiser les actions d'établissement d'une connexion pendant l'utilisation, c'est-à-dire d'essayer d'utiliser des connexions longues.

Mais après avoir utilisé de longues connexions, vous constaterez peut-être que parfois la mémoire occupée par MySQL augmente très rapidement.La mémoire temporairement utilisée par MySQL lors de l'exécution est gérée dans l'objet de connexion. . Ces ressources seront libérées lorsque la connexion sera déconnectée.Donc siL'accumulation de connexions longues peut entraîner une utilisation excessive de la mémoire., a été tué de force par le système (MOO). À en juger par le phénomène, MySQL a redémarré anormalement.

Comment résoudre ce problème? Vous pouvez envisager les deux options suivantes.

  • Débranchez périodiquement les longues connexions . Après l'avoir utilisé pendant un certain temps, ou après que le programme a déterminé qu'une requête volumineuse occupant de la mémoire a été exécutée, la connexion est déconnectée, puis la requête est requise puis reconnectée.
  • Si vous utilisez MySQL 5.7 ou une version plus récente, vous pouvez exécuter mysql_reset_connection pour réinitialiser les ressources de connexion. Ce processus ne nécessite pas de reconnexion ni de vérification des autorisations, mais restaurera la connexion à l'état où elle vient d'être créée.

Cache de requêtes

Une fois que MySQL a reçu une requête de requête, il ira d'abord dans le cache de requêtes pour voir si cette instruction a déjà été exécutée. Les instructions précédemment exécutées et leurs résultats peuvent être mis en cache directement en mémoire sous la forme de paires clé-valeur. La clé est l'instruction de requête et la valeur est le résultat de la requête. Si votre requête parvient à trouver la clé directement dans ce cache, alors la valeur sera renvoyée directement au client.

Si l'instruction n'est pas dans le cache de requêtes, la phase d'exécution se poursuit. Une fois l'exécution terminée, les résultats de l'exécution seront stockés dans le cache des requêtes. Vous pouvez voir que si la requête atteint le cache, MySQL peut renvoyer directement le résultat sans effectuer d'opérations complexes ultérieures, ce qui est très efficace.

Mais la plupart du temps je le feraiIl est recommandé de ne pas utiliser la mise en cache des requêtes ,pourquoi? Parce que la mise en cache des requêtes fait souvent plus de mal que de bien.

Le cache de requêtes est invalidé très fréquemment. Tant qu'une table est mise à jour, tous les caches de requêtes sur cette table seront effacés. Il est donc possible que vous ayez pris la peine de sauvegarder les résultats et qu'avant même de les utiliser, ils aient été effacés par une mise à jour. Pour les bases de données soumises à une forte pression de mise à jour, le taux de réussite du cache de requêtes sera très faible. A moins que votre entreprise ne dispose d’un tableau statique qui ne sera mis à jour qu’une fois de longue durée. Par exemple, s'il s'agit d'une table de configuration système, la requête sur cette table convient au cache de requêtes.

Heureusement, MySQL propose également cette méthode « d'utilisation à la demande ». Vous pouvez définir le paramètre query_cache_type sur DEMAND afin que le cache de requêtes ne soit pas utilisé pour les instructions SQL par défaut. Pour les instructions pour lesquelles vous êtes sûr de vouloir utiliser le cache de requêtes, vous pouvez utiliser SQL_CACHE pour le spécifier explicitement, comme l'instruction suivante :

select SQL_CACHE * from T where ID=10;
  • 1

il faut en être conscient,La version MySQL 8.0 supprime directement toute la fonction de cache de requêtes, ce qui signifie que cette fonction ne sera plus disponible à partir de la version 8.0.

Analyseur

Si le cache de requêtes n’est pas atteint, l’exécution réelle de l’instruction commence. Tout d’abord, MySQL doit savoir ce que vous voulez faire, il doit donc analyser l’instruction SQL.

Insérer la description de l'image ici

optimiseur

Insérer la description de l'image ici
Insérer la description de l'image ici

Actionneur

Insérer la description de l'image ici
Insérer la description de l'image ici

2. Système de journalisation : Comment une instruction de mise à jour SQL est-elle exécutée ?

Insérer la description de l'image ici

journal de refaire

Je ne sais pas si vous vous souvenez encore de l'article "Kong Yiji". Le directeur de l'hôtel possède un tableau rose spécialement utilisé pour enregistrer les dossiers de crédit des clients. S'il n'y a pas beaucoup de gens qui paient à crédit, il peut alors écrire le nom et le compte du client au tableau. Mais s'il y a trop de personnes ayant des comptes de crédit, il y aura toujours des moments où le tableau des fans ne pourra pas les suivre. À ce moment-là, le commerçant doit disposer d'un grand livre spécialement pour enregistrer les comptes de crédit.

Si quelqu’un souhaite rembourser un crédit ou une dette, le commerçant a généralement deux possibilités :

  • Une solution consiste à ouvrir directement le grand livre et à ajouter ou soustraire le compte de crédit ;
  • Une autre approche estNotez d'abord les comptes cette fois sur le tableau rose, puis sortez les livres de comptes après l'heure de clôture et calculez-les.

Lorsque les affaires sont en plein essor et que le comptoir est occupé, le commerçant choisira certainementle dernier , car la première opération est trop gênante. Tout d'abord, vous devez trouver l'enregistrement du compte de crédit total de cette personne. Pensez-y, il y a des dizaines de pages densément remplies. Pour trouver le nom, le commerçant devra peut-être mettre des lunettes de lecture et chercher lentement, il sortira le boulier pour calculer, et enfin réécrira le résultat. le grand livre.

Il est difficile de penser à tout ce processus. En revanche, il est plus facile de l’écrire d’abord sur le tableau rose. Pensez-y, si le commerçant n'a pas l'aide du tableau rose, il doit retourner le grand livre à chaque fois qu'il enregistre les comptes, l'efficacité n'est-elle pas insupportablement faible ?

De même, ce problème existe également dans MySQL. Si chaque opération de mise à jour doit être écrite sur le disque et que le disque doit également trouver l'enregistrement correspondant avant la mise à jour, le coût d'E/S et de recherche de l'ensemble du processus sera très élevé. Afin de résoudre ce problème, les concepteurs de MySQL ont utilisé une idée similaire au tableau rose du commerçant d'un hôtel pour améliorer l'efficacité des mises à jour.

L'ensemble du processus de coopération entre le tableau rose et le grand livre est en fait ce qui est souvent mentionné dans MySQL. WAL technologie,WAL Le nom complet estWrite-Ahead Logging, le point clé estÉcrivez d'abord le journal, puis écrivez sur le disque, c'est-à-dire écrivez d'abord le tableau rose, puis écrivez le livre de comptes lorsque vous n'êtes pas occupé.

Plus précisément, lorsqu'un enregistrement doit être mis à jour, le moteur InnoDB écrira d'abord l'enregistrement dans le journal redo (tableau rose) et mettra à jour la mémoire. À ce moment, la mise à jour est terminée. Dans le même temps, le moteur InnoDB mettra à jour l'enregistrement des opérations sur le disque au moment approprié, et cette mise à jour est souvent effectuée lorsque le système est relativement inactif, tout comme ce que fait le commerçant après la fermeture.

S'il n'y a pas beaucoup de comptes créditeurs aujourd'hui, le commerçant peut attendre l'heure de fermeture pour trier les articles. Mais que devons-nous faire s’il y a beaucoup de comptes créditeurs un certain jour et que le tableau rose est plein ? À cette époque, le commerçant devait abandonner son travail, mettre à jour certains des enregistrements de crédit du tableau rose dans le grand livre, puis effacer ces enregistrements du tableau rose pour faire de la place pour de nouveaux comptes.

De même, le journal redo d'InnoDB a une taille fixe. Par exemple, il peut être configuré comme un ensemble de 4 fichiers, chaque fichier mesure 1 Go. Ensuite, ce « tableau rose » peut enregistrer un total de 4 Go d'opérations. Commencez à écrire depuis le début, puis revenez au début pour écrire en boucle, comme le montre l'image ci-dessous.

Insérer la description de l'image ici
write pos est la position de l'enregistrement en cours. Il recule lors de l'écriture. Après avoir écrit à la fin du fichier n° 3, il revient au début du fichier n° 0. Le point de contrôle est la position actuelle à effacer, et il avance également et boucle. Avant d'effacer l'enregistrement, l'enregistrement doit être mis à jour dans le fichier de données.

L'espace entre la position d'écriture et le point de contrôle est la partie vide du « tableau rose » qui peut être utilisée pour enregistrer de nouvelles opérations. Si la position d'écriture rattrape le point de contrôle, cela signifie que le "tableau rose" est plein et qu'aucune nouvelle mise à jour ne peut être effectuée pour le moment. Vous devez d'abord arrêter et effacer certains enregistrements pour avancer le point de contrôle.

Avec le redo log, InnoDB peut garantir que même si la base de données redémarre anormalement, les enregistrements précédemment soumis ne seront pas perdus. Cette capacité est appelée.crash-safe

Pour comprendre le concept de sécurité en cas de crash, pensez à notre précédent exemple de dossier de crédit. Tant que le dossier de crédit est enregistré sur le tableau rose ou écrit sur le grand livre, même si le commerçant l'oublie plus tard, par exemple en suspendant soudainement son activité pendant quelques jours, il peut toujours clarifier le compte de crédit grâce aux données du grand livre et tableau rose après la reprise des activités.

journal binaire

Comme nous l'avons dit précédemment, MySQL dans son ensemble comprend en réalité deux parties : l'une est la couche serveur, qui s'occupe principalement des tâches au niveau fonctionnel de MySQL ; l'autre est la couche moteur, qui est responsable des questions spécifiques liées au stockage.Le tableau rose dont nous parlions plus hautredo log est un journal unique au moteur InnoDB,et La couche Serveur possède également son propre journal, appelé binlog (journal d'archive)

Je pense que vous vous demanderez pourquoi y a-t-il deux journaux ?

Parce qu'il n'y avait pas de moteur InnoDB dans MySQL au début. Le propre moteur de MySQL est MyISAM, mais MyISAM n'a pas de fonctionnalités de sécurité contre les pannes et les journaux binlog ne peuvent être utilisés qu'à des fins d'archivage. InnoDB a été introduit dans MySQL sous la forme d'un plug-in par une autre société. Étant donné que le fait de s'appuyer uniquement sur binlog n'a pas de capacités de sécurité contre les crashs, InnoDB utilise un autre système de journalisation, à savoir le redo log, pour obtenir des capacités de sécurité contre les crashs.

Ces deux journaux présentent les trois différences suivantes.

  1. Le redo log est unique au moteur InnoDB ; le binlog est implémenté par la couche serveur de MySQL et peut être utilisé par tous les moteurs.
  2. le journal redo est un journal physique, enregistre "quelles modifications ont été apportées sur une certaine page de données" ;binlog est un journal logique, ce qui est enregistré est la logique originale de cette instruction, telle que "ajouter 1 au champ c de la ligne avec ID=2".
  3. le redo log est écrit en boucle, l'espace sera utilisé ;binlog peut être écrit en plus . "Ajouter l'écriture" signifie qu'une fois que le fichier binlog atteint une certaine taille, il passera au suivant et n'écrasera pas le journal précédent.

Avec une compréhension conceptuelle de ces deux journaux, examinons les processus internes de l'exécuteur et du moteur InnoDB lors de l'exécution de cette simple instruction de mise à jour.

  1. L'exécuteur recherche d'abord le moteur pour obtenir l'ID de ligne = 2. L'ID est la clé primaire et le moteur utilise directement la recherche arborescente pour trouver cette ligne. Si la page de données où se trouve la ligne avec ID=2 est déjà dans la mémoire, elle sera renvoyée directement à l'exécuteur sinon, elle doit d'abord être lue dans la mémoire à partir du disque puis renvoyée ;
  2. L'exécuteur récupère les données de ligne fournies par le moteur, ajoute 1 à cette valeur, par exemple, c'était N avant, mais maintenant c'est N+1, obtient une nouvelle ligne de données, puis appelle l'interface du moteur pour écrire ceci nouvelle ligne de données.
  3. Le moteur met à jour cette nouvelle ligne de données dans la mémoire et enregistre l'opération de mise à jour dans le journal redo. journal de refaire danspréparer État. Informez ensuite l'exécuteur testamentaire que l'exécution est terminée et que la transaction peut être soumise à tout moment.
  4. L'exécuteur génère un binlog de cette opération et met binlog écrit sur le disque
  5. L'exécuteur appelle l'interface de transaction de validation du moteur et le moteur écrit le journal de refaire Modification à soumettre (commettre), la mise à jour est terminée.

Ici, je donne l'organigramme d'exécution de cette instruction de mise à jour. La case lumineuse dans la figure indique qu'elle est exécutée dans InnoDB, et la case sombre indique qu'elle est exécutée dans l'exécuteur.

Insérer la description de l'image ici
processus d'exécution de l'instruction de mise à jour

Vous avez peut-être remarqué que les trois dernières étapes semblent un peu « circulaires ». L'écriture du redo log est divisée en deux étapes : préparer et valider. Il s'agit d'un « commit en deux phases ».

engagement en deux phases

Pourquoi faut-il une « soumission en deux phases » ?Ceci permet de faire la différence entre les deux journauxlogiquement cohérent . Pour expliquer ce problème, nous devons commencer par la question du début de l'article : Comment restaurer la base de données à l'état d'une seconde en un demi-mois ?

Comme nous l'avons déjà dit, binlog enregistrera toutes les opérations logiques et adoptera la forme d'une « écriture d'ajout ». Si votre administrateur de base de données promet qu'il peut être restauré dans un délai d'un demi-mois, le système de sauvegarde enregistrera définitivement tous les journaux binaires au cours du dernier demi-mois et le système effectuera des sauvegardes régulières de l'ensemble de la base de données. Le « régulier » dépend ici de l'importance du système, qui peut être une fois par jour ou une fois par semaine.

Lorsque vous devez restaurer à une seconde spécifiée, par exemple, à deux heures de l'après-midi un jour, vous constatez qu'une table a été accidentellement supprimée à midi et que vous devez récupérer les données, vous pouvez procéder comme suit :

  • Tout d'abord, recherchez la sauvegarde complète la plus récente. Si vous avez de la chance, il peut s'agir d'une sauvegarde d'hier soir et restaurez à partir de cette sauvegarde vers la base de données temporaire.
  • Ensuite, à partir du moment de la sauvegarde, les journaux binaires de sauvegarde sont supprimés dans l'ordre et relus jusqu'à l'heure précédant la suppression accidentelle de la table à midi.
    De cette façon, votre base de données temporaire sera la même que la base de données en ligne avant que vous ne la supprimiez accidentellement. Vous pourrez ensuite retirer les données de la table de la base de données temporaire et les restaurer dans la base de données en ligne si nécessaire.

D'accord, après avoir parlé du processus de récupération des données, revenons et expliquons pourquoi le journal nécessite une « validation en deux phases ». Ici, autant utiliser la preuve par contradiction pour expliquer.

Étant donné que le redo log et le binlog sont deux logiques indépendantes, si la validation en deux phases n'est pas utilisée, soit le redo log doit être écrit en premier, puis le binlog doit être écrit, soit l'ordre inverse doit être adopté. Voyons quels sont les problèmes liés à ces deux méthodes.

Utilisez toujours l'instruction de mise à jour précédente comme exemple. Supposons que la valeur du champ c dans la ligne actuelle avec ID=2 soit 0, et supposons que lors de l'exécution de l'instruction de mise à jour, un crash se produise après l'écriture du premier journal mais avant l'écriture du deuxième journal. Que se passera-t-il ?

  • Écrivez d'abord le journal de rétablissement, puis le journal binlog.
    Supposons que le processus MySQL redémarre anormalement lorsque le journal redo est écrit mais avant l'écriture du binlog. Comme nous l'avons dit précédemment, une fois le journal redo écrit, même si le système tombe en panne, les données peuvent toujours être restaurées, donc la valeur de c dans cette ligne après la récupération est 1. Cependant, comme le journal binaire s'est écrasé avant d'être terminé, cette instruction n'a pas été enregistrée dans le journal binaire pour le moment. Par conséquent, lorsque le journal sera sauvegardé ultérieurement, cette instruction ne sera pas incluse dans le journal binaire enregistré. Ensuite, vous constaterez que si vous devez utiliser ce binlog pour restaurer la bibliothèque temporaire, car le binlog de cette instruction est perdu, la bibliothèque temporaire ne sera pas mise à jour cette fois. La valeur de c dans la ligne restaurée est 0, ce qui est. la même chose que la valeur de la bibliothèque d'origine différente.
  • Écrivez d'abord binlog, puis refaites le journal.
    S'il y a un crash après l'écriture du binlog, puisque le redo log n'a pas encore été écrit, la transaction sera invalide après la récupération sur crash, donc la valeur de c dans cette ligne est 0. Mais le journal "Changer c de 0 à 1" a été enregistré dans le binlog. Par conséquent, lorsque binlog est utilisé pour restaurer ultérieurement, une transaction supplémentaire sera générée. La valeur de c dans la ligne restaurée est 1, ce qui est différent de la valeur dans la base de données d'origine.
    On constate que si la « validation en deux phases » n'est pas utilisée, l'état de la base de données peut être incohérent avec l'état de la bibliothèque restaurée à l'aide de son journal.

Vous pourriez vous demander : cette probabilité est-elle très faible ? Il n’existe aucune situation dans laquelle la bibliothèque temporaire doit être restaurée à tout moment.

En fait non, ce processus n’est pas seulement nécessaire pour récupérer des données après une mauvaise opération. Lorsque vous avez besoin d'étendre la capacité, c'est-à-dire lorsque vous devez créer davantage de bases de données de sauvegarde pour augmenter la capacité de lecture du système, la pratique courante consiste désormais à utiliser une sauvegarde complète et à appliquer binlog pour y parvenir. Cette "incohérence" entraînera votre présence. est une incohérence entre les bases de données maître et esclave en ligne.

En termes simples, redo log et binlog peuvent être utilisés pour représenter l'état de validation d'une transaction, etLa soumission en deux phases vise à maintenir la cohérence logique des deux États.