web-dev-qa-db-ja.com

MySQLスレーブが「リレーログへのマスターイベントのキューイング」に時間がかかりすぎる

2つのmysql mysqlスレーブサーバーがあります。 DBバージョンは次のとおりです。

mysql> show variables like '%version%';
+-------------------------+-----------------------------------------------------+
| Variable_name           | Value                                               |
+-------------------------+-----------------------------------------------------+
| innodb_version          | 1.1.8-rel29.4                                       |
| protocol_version        | 10                                                  |
| slave_type_conversions  |                                                     |
| version                 | 5.5.29-29.4-log                                     |
| version_comment         | Percona Server (GPL), Release rel29.4, Revision 401 |
| version_compile_machine | x86_64                                              |
| version_compile_os      | Linux                                               |
+-------------------------+-----------------------------------------------------+
7 rows in set (0.00 sec)

開発者はマスターで大きなテーブルを再構築する必要があり、その後スレーブのステータスは次のように表示されます。

show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Queueing master event to the relay log
                  Master_Host: 10.140.10.31
                  Master_User: replicator
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000100
          Read_Master_Log_Pos: 246814935
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 163153081
        Relay_Master_Log_File: mysql-bin.000100
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: temp
           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: 244925740
              Relay_Log_Space: 165042426
              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: 10
1 row in set (0.01 sec)

Seconds_Behind_Master: 0値が0から短期間に多数に変化し、その後再び0に戻ります。マスターDBの変更がスレーブにまだ書き込まれていないことを確認しました。

スレーブのDISKアクティビティを確認しましたが、DISKの使用率はまだ非常に高く、リレーログに書き込んでいることを示しています。

# iostat -dx 1
Linux 2.6.32-279.19.1.el6.centos.plus.x86_64 (hmg-slave-hoteldata2)     09/04/2014      _x86_64_        (4 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.01     8.99    0.49    9.65    23.04   213.78    23.34     0.05    4.45   2.28   2.31
dm-0              0.00     0.00    0.01    0.01     0.04     0.05     8.00     0.00   23.31   1.11   0.00
dm-1              0.00     0.00    0.50   18.64    23.00   213.74    12.36     0.18    9.33   1.21   2.31

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00   321.00    0.00  337.00     0.00  5264.00    15.62     0.87    2.59   2.59  87.20
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00  658.00     0.00  5264.00     8.00     1.22    1.86   1.32  87.10

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00   315.00    0.00  345.00     0.00  5280.00    15.30     0.87    2.50   2.50  86.40
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00  660.00     0.00  5280.00     8.00     1.27    1.92   1.31  86.40

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00   324.00    0.00  345.00     0.00  5352.00    15.51     0.86    2.50   2.50  86.10
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00  669.00     0.00  5352.00     8.00     1.20    1.80   1.29  86.10

テーブルを再構築するために実行されたクエリは次のとおりです。

case 'TWN': 
        $query = "INSERT INTO Hotels.AllHotelImagesBAK (hmid, Caption, URL, Width, Height, PopOutURL, ThumbnailURL, `Default`, Source, ValidSize)
                    SELECT hmid, Caption, MainURL, Width, Height, PopOutURL, ThumbnailURL, DefaultImage, 'TWN', 'Y'
                        FROM FeedHotels.LondonTownImages 
                        INNER JOIN Hotels.HotelFeedLookup ON feedHotelID=HotelID AND feedID='TWN'
                        WHERE HotelID IN ('" . implode("','", $hotelIDs) . "')";
        break;
case 'EXP':
case 'XPP':  
        $query = "INSERT INTO Hotels.AllHotelImagesBAK (hmid, Caption, URL, Width, Height, PopOutURL, ThumbnailURL, `Default`, Source)
                    SELECT hmid, Caption, URL, Width, Height, URL, ThumbnailURL, `Default`, 'EXP' 
                        FROM FeedHotels.ExpediaImages
                        INNER JOIN Hotels.HotelFeedLookup ON feedHotelID=HotelID AND feedID='" . $feed->id . "'
                        WHERE feedHotelID IN ('" . implode("','", $hotelIDs) . "')";
        break;
case 'ORB': 
        $query = "INSERT INTO Hotels.AllHotelImagesBAK (hmid, URL, PopOutURL, ThumbnailURL, Source)
                    SELECT hmid, URL, URL, URL, 'ORB'
                        FROM FeedHotels.OrbitzImages 
                        INNER JOIN Hotels.HotelFeedLookup ON feedHotelID=HotelID AND feedID='ORB'
                        WHERE feedHotelID IN ('" . implode("','", $hotelIDs) . "')";
        break;
case 'HRS': 
        $query = "INSERT INTO Hotels.AllHotelImagesBAK (hmid, Caption, URL, Width, Height, PopOutURL, ThumbnailURL, `Default`, Source, ValidSize)
                    SELECT hmid, Location, URL, Width, Height, URL, URL, IF(`Default`='Y', 1, 0),'HRS','Y'
                        FROM FeedHotels.HRSImages 
                        INNER JOIN Hotels.HotelFeedLookup ON feedHotelID=HotelID AND feedID='HRS'
                        WHERE feedHotelID IN ('" . implode("','", $hotelIDs) . "')";
        break;
}

これを引き起こしている原因と解決方法を知りたいと思います。何か助けは?

3
mezi

大きなテーブルがLOAD DATA INFILEを使用してマスターにリロードされた場合、次のようになります。

  • リレーログは、入力ファイル全体を転送するために使用されています。
  • 入力ファイルは、リレーログから一時ファイルに抽出する必要があります。
  • スレーブは、抽出された一時ファイルに対してLOAD DATA INFILEを実行する必要があります。

このプロセスについては、以前にDBA StackExchangeで説明しました

MySQLレプリケーションでこのプロセスを完了する必要があります。

UPDATE 2014-09-07 15:40 EDT

リレーログが増大して大量の書き込みI/Oが発生する理由を明らかにする可能性のある実用的な理論があり、Seconds_Behind_Masterはまだ0です。

Binlog_formatがROWまたはMIXEDに設定されている場合、SELECTを構成するすべての行がLOAD DATA INFILEと同じ方法でリレーログに埋め込まれているように見えますが、同じメカニズムではありません。どうして ?

LOAD DATA INFILEは、CSVファイルをbinlogイベントチャンクに埋め込み、スレーブでCSVファイルを抽出および表示できるようにします。 INSERT ... SELECTSELECTを単一のトランザクションとして扱う必要があります。次に、INSERTの一部としてすべての行の変更をインポートします。そのためには、マスターとスレーブでbinlog_format ROWまたはMIXEDを使用する必要があります。 binlog_format STATEMENTを使用している場合、ステートメントはスレーブのリレーログに即座に到達し、Seconds_Behind_Masterはすぐに上昇を開始する必要があります。

MySQL DocumentationがINSERT ... SELECT について述べているため、これは私の疑いです。

この問題のため、MySQL 5.6.4以降では、INSERT ... SELECT ON DUPLICATE KEY UPDATEおよびINSERT IGNORE ... SELECTステートメントに、ステートメントベースのレプリケーションでは安全でないというフラグが立てられます。この変更により、このようなステートメントは、ステートメントベースモードを使用する場合はログに警告を生成し、MIXEDモードを使用する場合は行ベースのフォーマットを使用してログに記録されます。 (バグ#11758262、バグ#50439)

これらのバグレポートを見ると、これはまったく新しい視点をとります

MySQL 5.5.18がリリースされたとき 、このバグは修正されるはずでした

修正されたバグ

  • 互換性のない変更:レプリケーション:次のリストのステートメントは、ステートメントベースのレプリケーションでは安全でないとマークされています。これは、これらの各ステートメントが、順序を常に決定できるとは限らないSELECTステートメントの結果に依存するためです。 STATEMENTロギングモードを使用すると、これらのステートメントのいずれかについて警告がバイナリログに発行されます。 MIXEDロギングモードを使用する場合、ステートメントは行ベースのフォーマットを使用してログに記録されます。

    • 挿入...選択...重複キー更新時

    • 交換...選択

    • CREATE TABLE ... IGNORE SELECT

    • CREATE TABLE ... REPLACE SELECT

    • 無視を挿入...選択

    • UPDATE IGNOREアップグレードする場合、アプリケーションでのこれらのステートメントの使用に注意する必要があります。SELECTから取得した行を挿入または置換するステートメントは、行ベースを使用してログに記録すると、バイナリログの何倍ものスペースを占める可能性があることに注意してください。ステートメント自体のみがログに記録される場合よりもフォーマット。このようなステートメントによって選択および挿入(または置換)された行の数とサイズに応じて、これらのステートメントのロギングがステートメントベースから行ベースに切り替えられた後のバイナリログのサイズの違いは、潜在的にいくつかの順序になる可能性があります大きさの。 15.1.2.1項「文ベースおよび行ベースのレプリケーションの長所と短所」を参照してください。 (バグ#11758262、バグ#50439)

あなたは言うその部分を見ましたか

a statement that
inserts or replaces rows obtained from a SELECT can take up
many times as much space in the binary log when logged using
row-based format than when only the statement itself is
logged. Depending on the number and size of the rows selected
and inserted (or replaced) by any such statements, the
difference in size of the binary log after the logging of
these statements is switched from statement-based to row-based
can potentially be several orders of magnitude

これは、5.5.18より前のバージョンのMySQLまたはこのパッチを適用していないバージョンのMySQLを使用しているために発生している可能性があります。

Binlog_format STATEMENTに切り替えると、リレーログの増加、ディスクI/Oの増加、およびSeconds_Behind_Masterがまだ0であるというこの現象は解消されます。それか、MySQLをアップグレードします。

2014-09-08 08:06 EDTの更新

明確にさせてください。個人的には、私は binlog_format ROWが好きではありません。バイナリログとリレーログが肥大化するためです。この投稿では、STATEMENTを使用すると述べました。それは私の好みです。私が言うより正しいのは、マスターとそのスレーブをまったく同じにする binlog_format です。すべてを混ぜ合わせてください。弾丸を噛み、スレーブを最初から再同期する必要があります。

3
RolandoMySQLDBA