Réplication MySQL - l'esclave est constamment en retard sur le maître


12

J'utilise MySQL-5.1.50 avec une configuration de réplication maître-esclave.

La plupart du temps, l'esclave est en retard sur le maître.

Lorsque je cours show processlist;, aucune requête ne prend beaucoup de temps. J'ai également activé slow_log. Cependant, il ne trouve aucune requête à exécution lente.

L'esclave avertit en permanence que la réplication est à quelques secondes du maître. Parfois, le temps de latence augmente.

Comment diagnostiquer la cause du problème?

J'ai besoin d'une aide urgente, car ce problème persiste depuis 20 jours.


Réponses:


20

Le Seconds_Behind_Master est vraiment comme regarder le passé via un voyage dans le temps.

Pense-y de cette façon:

  • Le Soleil est à 93 000 000 miles de la Terre
  • La vitesse de la lumière est de 186 000 miles / sec
  • Une division simple montre qu'il faut environ 500 secondes (8 min 20 secondes) pour que la lumière du soleil atteigne la Terre
  • Lorsque vous regardez le soleil, vous ne voyez pas réellement le soleil. Vous voyez où c'était il y a 8 min 20 sec.

De la même manière, il semble que le maître traite beaucoup de requêtes en même temps.

Vous regardez en arrière l'esclave, courez SHOW SLAVE STATUS\Get ça dit 200 pour Seconds_Behind_Master. Comment ce nombre est-il calculé? Heure de l'horloge de l'esclave (UNIX_TIMESTAMP (NOW ()) - TIMESTAMP de la requête lorsqu'elle a été terminée et enregistrée dans le journal binaire du maître.

Il y a une autre métrique à regarder en plus Seconds_Behind_Master. Cette métrique est appelée Relay_Log_Space. Cela représente la somme de tous les octets pour tous les fichiers relais sur l'esclave. Par défaut, le plus grand journal de relais unique est limité à 1 Go. Si Relay_Log_Spaceest inférieur à 1 Go, cela indique que de nombreuses requêtes longues exécutées sur le maître en parallèle. Malheureusement, en raison du thread SQL de la réplication à un seul thread, les requêtes sont exécutées les unes derrière les autres.

Par exemple, supposons que vous ayez le scénario suivant sur le maître:

  • Le journal des requêtes lentes est activé
  • 20 requêtes exécutées en parallèle sur le Master
  • Chaque requête a pris 3 secondes
  • Chaque requête est enregistrée dans le journal binaire principal avec le même horodatage

Lorsque l'esclave lit ces requêtes dans son journal de relais et les traite une par une

  • l'horloge de l'esclave se déplacera
  • le TIMESTAMP pour chacune des 20 requêtes sera identique
  • la différence augmentera de 3 secondes soit terminée
  • cela se traduit en 60 secondes pour Seconds_Behind_Master

Concernant le journal lent, la valeur par défaut pour long_query_time est de 10 secondes. Si toutes vos requêtes dans les journaux de relais sont inférieures à 10 secondes, vous n'attraperez jamais rien dans le journal des requêtes lentes.

J'ai les recommandations suivantes pour les serveurs maître et esclave

DÉPANNAGE SUPPLÉMENTAIRE

Si vous souhaitez voir les requêtes provoquant le retard de replciation, procédez comme suit:

  • SHOW SLAVE STATUS\G
  • Obtenir le nom du journal de relais de Relay_Log_File
  • STOP SLAVE;
  • START SLAVE;
  • Dans le système d'exploitation, cd /var/lib/mysqlou partout où les journaux de relais sont écrits
  • Vider le journal de relais dans un fichier texte

Par exemple, faisons SHOW SLAVE STATUS\G

               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.64.51.149
                  Master_User: replicant
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000009
          Read_Master_Log_Pos: 1024035856
               Relay_Log_File: relay-bin.000030
                Relay_Log_Pos: 794732078
        Relay_Master_Log_File: mysql-bin.000009
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB: search_cache
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1024035856
              Relay_Log_Space: 794732271
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 106451149

Si je cours STOP SLAVE; START SLAVE;, le journal du relais se ferme et un nouveau est ouvert. Pourtant, tu veux relay-bin.000030.

Vider le contenu comme suit:

cd /var/lib/mysql
mysqlbinlog relay-bin.000030 > /root/RelayLogQueries.txt
less /root/RelayLogQueries.txt

Vous pouvez maintenant voir les requêtes que l'esclave essaie actuellement de traiter. Vous pouvez utiliser ces requêtes comme point de départ pour l'optimisation.


Depuis la v5.7, MySQL est capable d'appliquer des modifications aux esclaves de manière multi-thread. La documentation connexe peut être trouvée ici: dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html
edigu

2

Quel format de journal binaire utilisez-vous? Utilisez-vous ROW ou STATEMENT?
" SHOW GLOBAL VARIABLES LIKE 'binlog_format';"

Si vous utilisez ROW comme format binlog, assurez-vous que toutes vos tables ont une clé primaire ou unique:
SELECT t.table_schema,t.table_name,engine FROM information_schema.tables t INNER JOIN information_schema .columns c on t.table_schema=c.table_schema and t.table_name=c.table_name and t.table_schema not in ('performance_schema','information_schema','mysql') GROUP BY t.table_schema,t.table_name HAVING sum(if(column_key in ('PRI','UNI'), 1,0)) =0;

Si vous exécutez par exemple une instruction de suppression sur le maître pour supprimer 1 million d'enregistrements sur une table sans PK ou clé unique, alors un seul balayage complet de la table aura lieu du côté du maître, ce qui n'est pas le cas de l'esclave.
Lorsque ROW binlog_format est utilisé, MySQL écrit les modifications de lignes dans les journaux binaires (pas sous la forme d'une instruction comme STATEMENT binlog_format) et cette modification sera appliquée ligne par ligne de l'esclave, ce qui signifie qu'un scan complet de 1 million de tables aura lieu sur l'esclave pour ne refléter qu'une seule instruction de suppression sur le maître et cela cause un problème de retard de l'esclave.


0

La valeur seconds_behind_master dans SHOW SLAVE STATUS est la différence entre l'heure système sur le maître, qui a été stockée lorsque l'événement a été initialement exécuté et enregistré dans le journal binaire ... et l'heure système sur l'esclave lorsque l'événement y est exécuté.

Les secondes derrière master donneront des valeurs incorrectes si les horloges des deux systèmes ne sont pas synchronisées.


Dans MySQL 5.5 et versions antérieures, l'exécution des événements de réplication est monothread côté esclave. Il devrait y avoir deux threads dans "SHOW FULL PROCESSLIST" s'exécutant en tant qu '"utilisateur système" - l'un reçoit les événements du maître, l'autre exécute les requêtes. Si l'esclave est en retard, ce thread devrait montrer quelle requête est en cours d'exécution. Jetez un oeil à cela, et regardez également dans vos statistiques de disque / mémoire / cpu pour une famine de ressources.
Michael - sqlbot
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.