深さ分析|MGR同じGTIDで異なるtransaction故障分析を発生


本文は愛可生運維チームが出品した「MySQLコラム」シリーズの文章で、内容は運維チームの第一線の実戦経験から来て、MySQLの各種特性の実践をカバーして、ケースを最適化して、データベースのアーキテクチャ、HA、監視など、掃雷の効果があります.
愛可生オープンソースコミュニティの持続的な運営と維持の小さな目標:
  • 毎週少なくとも1つの高品質技術文書をプッシュ・
  • 毎月研究開発チームがオープンソースコンポーネントの新版を発表
  • 毎年1024オープンソース1つのエンタープライズ・コンポーネント
  • 2019年少なくとも25回のコミュニティ活動
  • 引き続きご注目ください~
    MGRはMySQLのオリジナルの高可用性スキームとして、共通認識プロトコルに基づく同期と意思決定メカニズムもより先進的に見えます.MGRアーキテクチャによりRPO=0の高可用性切り替えを解決したいという一票のユーザーの積極的な試みを引きつけた.実際の使用では、ネットワークのジッタの問題でクラスタ障害が発生することがよくありますが、最近、お客様がこのような問題に遭遇し、データが一致しません.
    もんだいげんしょう
    これは、同じGTID 86 afb 16 f-1 b 8 c-11 e 8-812 f-05050568912 a 4:57305280で同じトランザクションを実行する必要があるが、binlogログには異なるトランザクション情報が表示されるMGRクラスタのセットです.
  • Primaryノードbinlog:
  • SET @@SESSION.GTID_NEXT= '86afb16f-1b8c-11e8-812f-0050568912a4:57305280'/*!*/;# at 637087357#190125 15:02:55 server id 3136842491 end_log_pos 637087441 Querythread_id=19132957 exec_time=0 error_code=0SET TIMESTAMP=1548399775/*!*/;BEGIN/*!*/;# at 637087441#190125 15:02:55 server id 3136842491 end_log_pos 637087514 Table_map:`world`.`IC_WB_RELEASE` mapped to number 398# at 637087514#190125 15:02:55 server id 3136842491 end_log_pos 637087597 Write_rows: table id 398flags: STMT_END_FBINLOG 'n7RKXBP7avi6SQAAABov+SUAAI4BAAAAAAEAB2ljZW50ZXIAFUlDX1FVRVJZX1VTRVJDQVJEX0xP'/*!*/;### INSERT INTO `world`.`IC_WB_RELEASE`### SET
  • Secondaryノードbinlog:
  • SET @@SESSION.GTID_NEXT= '86afb16f-1b8c-11e8-812f-0050568912a4:57305280'/*!*/;# at 543772830#190125 15:02:52 server id 3136842491 end_log_pos 543772894 Querythread_id=19162514 exec_time=318 error_code=0SET TIMESTAMP=1548399772/*!*/;BEGIN/*!*/;# at 543772894#190125 15:02:52 server id 3136842491 end_log_pos 543772979 Table_map:`world`.`IC_QUERY_USERCARD_LOG` mapped to number 113# at 543772979#190125 15:02:52 server id 3136842491 end_log_pos 543773612 Delete_rows: table id113 flags: STMT_END_FBINLOG 'nLRKXBP7avi6VQAAADNRaSAAAHEAAAAAAAEAB2ljZW50ZXIADUlDX1dCX1JFTEVBU0UACw8PEg8'/*!*/;### DELETE FROM `world`.`IC_QUERY_USERCARD_LOG`### WHERE

    以上の情報から、primaryノードはこのGTIDの下でworld.IC_WB_RELEASEテーブルはinsert操作イベントを実行してsecondaryノードに同期していない.secondaryノードはプライマリノードの他のイベントを受信し、データが一致しない.テーブルIC_にWB_RELEASEでdelete操作が発生した場合、次のような障害が発生し、ノードからクラスタを離脱します.
    2019-01-28T11:59:30.919880Z 6 [ERROR] Slave SQL for channel 'group_replication_applier': Could not execute Delete_rows event on table `world`.`IC_WB_RELEASE`; Can't find record in 'IC_WB_RELEASE', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND, Error_code: 10322019-01-28T11:59:30.919926Z 6 [Warning] Slave: Can't find record in 'IC_WB_RELEASE' Error_code: 10322019-01-28T11:59:30.920095Z 6 [ERROR] Plugin group_replication reported: 'The applier thread execution was aborted. Unable to process more transactions, this member will now leave the group.'2019-01-28T11:59:30.920165Z 6 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'FIRST' position 271.2019-01-28T11:59:30.920220Z 3 [ERROR] Plugin group_replication reported: 'Fatal error during execution on the Applier process of Group Replication. The server will now leave the group.'2019-01-28T11:59:30.920298Z 3 [ERROR] Plugin group_replication reported: 'The server was automatically set into read only mode after an error was detected.'

    もんだいぶんせき
  • マスターノードがスレーブノードにトランザクションを同期する際、少なくとも1つのGTIDが86 afb 16 f-1 b 8 c-11 e 8-812 f-05050568912 a 4:57305280(insert操作を実行している)のトランザクションがスレーブノードに同期していない場合、このGTIDはインスタンスから存在しない.従って、マスターインスタンスGTIDはスレーブインスタンスよりも高い.データはもう一致していません.
  • クラスタ業務は正常に行われ、GTIDは上昇し続け、新たに上昇したGTIDはインスタンスから86 afb 16 f-1 b 8 c-11 e 8-812 f-05050568912 a 4:57305280というGTIDに同期したため、インスタンスからinsert操作を実行せず、データの一部が少なくなった.
  • マスタノードは、GTID 86 afb 16 f-1 b 8 c-11 e 8-812 f-050568912 a 4:57305280で実行されたinsertデータをdeleteし、ノードから元のinsert操作に同期していないため;この部分のデータがなければdeleteはできず,クラスタから離れた.

  • この障害の解析については,主従インスタンスGTIDは同じであるが,トランザクションが異なる原因から,この問題はバグ(https://bugs.mysql.com/bug.ph...)について,MGR同期トランザクションのタイミングについて以下のように分析した.
    関連知識の背景
    MGRの全グループ同期データのXcomコンポーネントはpaxosアルゴリズムに基づく実現である.プライマリ・インスタンスは、新しいトランザクションをコミットするたびに、インスタンスから交渉するために新しいトランザクションを送信し、グループ内の交渉が通過した後、グループ全体のメンバーが一緒にトランザクションをコミットします.各ノードは同じ順序で同じトランザクション・ログを受信するため、各ノードは同じ順序でこれらのトランザクションを再生し、最終グループ内で一貫した状態を維持します.
    paxosには2つのロールがあります.
    提案者(Proposer):積極的に投票主を発起し、提案を発起することを許可する.受信者(Acceptor):提案者(Proposer)の提案を受動的に受信し、記録し、フィードバックしたり、共通認識の提案を学習したりします.
    paxosが合意したプロセスには、2つの段階が含まれています.
    第一段階(prepare)
    a:提案者(Proposer)はprepareリクエストを送信し、独自の提案ID(ballot、数値番号とノード番号からなる)とvalue値を添付する.グループメンバーはprepareリクエストを受信します.b:自身に確認された値がある場合は、その値をack_prepare形式フィードバック;この段階では,Proposerはack返信を受け取るとballot値を比較し,数値の大きいballotは数値の小さいballotに取って代わる.ほとんどの応答を受け取ってから次の段階に入ると.
    第2段階(accept)
    a:提案者(Proposer)はaccept要求bを送信する:受信者(Acceptor)は要求を受信した後、自身の以前のbollatが同じかどうかとvalue値を受信したかどうかを比較する.value値とballotが同じでない場合はack_を返します.accept、value値を受信した場合、最大ballotを選択してack_を返します.accept.c:その後同じvalue値を受け入れるProposerノードからlearn_を送信op,learnを受け取るopノードの例は,データ修正を確認し,上位アプリケーションに渡すことを示す.
    この例では、いくつかのキーを強調する必要があります.
  • 1.このケースの最も根本的な異常対比は2回目の提案のprepare段階で発生した.
  • 2.prepareフェーズの提案識別は、数値番号とノード番号の2つの部分から構成される.ここで、数値番号は自己成長値に似ていますが、ノード番号は変わりません.

  • 分析プロセス
    paxosシーケンスと組み合わせて、ケース・プロシージャを推測します.
    Tips:以下の分析プロセスは、タイミングチャートの操作手順に従ってご覧ください
    ポイント開放が大きく、より効果的であることをお勧めします^^
  • 【step 1】primaryノードがテーブルworldを実行する.IC_WB_RELEASEのinsert操作は、ballotを(0.0)に設定し、value値worldをグループ内に送信.IC_WB_RELEASEのprepareリクエスト、そして大多数のメンバーのack_を受け取りますprepareが返され、acceptリクエストの送信が開始されます.primaryノードはballot(0.0)の提案情報をグループに送信し、ほとんどのメンバーack_を受信した.accept(ballot=0.0 value=world.IC_WB_RELEASE)が返されます.そしてlearn_を送信op情報【step 3】.
  • 同時に他のスレーブノードがネットワーク上の理由でプライマリインスタンスのlearn_を受け取っていないop情報【step 3】のうちの1台はインスタンスから新しいprepare要求【step 2】を開始し、要求value値はno_op(空の操作)ballot=1.1(この番号ではノード番号がキーであり、このsecondaryノード番号がprimaryノード番号より大きく、数値番号が誰が大きくても誰が小さくても初期化されるという後続の問題が発生します).

  • 他のスレーブインスタンスは、プライマリノードのvalue値が受信されたためである.したがって、プライマリノードの(ballot=0.0、value=world.IC_WB_RELEASE)を返します.受け取ったack_prepareのballot値の数値記号は全グループで0に初期化され、ballot全体のサイズはノード番号によって完全に決定されるので、ノードからballotの大きいこのインスタンスvalue値を新しい提案として選択し、メインインスタンスのvalue値を上書きし、多くのメンバーのack_を受け取るaccept【step2】.グループメンバー間でlearn_を送信しましたop情報【step 3】は,プライマリインスタンスが提案したトランザクションをスキップする.
    ソースコードからhandle_についてack_prepareの論理.
    handle_ack_prepare has the following code:    if (gt_ballot(m->proposal,p->proposer.msg->proposal))        {            replace_pax_msg(&p->proposer.msg, m);            ...            }
  • このとき、マスターノードはacceptフェーズでグループ内の大多数のメンバーからack_を受け取ったacceptは自分が送ったlearnを受け取った.op情報は,86 afb 16 f−1 b 8 c−11 e 8−812 f−05050568912 a 4:57305280のトランザクションGTIDを持つ自分の提案(すなわちbinlogにおけるテーブルに対するinsert操作)を[step 3]に提出する.他のノードの提案はno_op【step 3】なので、トランザクションはコミットされません.このとき、マスターインスタンスGTIDは、他のスレーブインスタンスよりも大きい.
  • メインノード新生GTIDは引き続き上昇する;スレーブインスタンスに同期すると、スレーブインスタンスの86 afb 16 f−1 b 8 c−11 e 8−812 f−050568912 a 4:57305280というGTIDが占有され、マスターノードがスレーブノードbinlogと同じであるがトランザクションが異なる現象が生じる.
  • 業務が対表worldに実行するとき.IC_WB_RELEASEのdelete操作の場合,主インスタンスは操作できるが,他のインスタンスはinsertがデータをオーバーしていないため操作できず,クラスタから離脱している.

  • ▲過程まとめ:
  • 旧主はprepareリクエストを送信し、大多数のackを受け取り、accept段階に入り、大多数のackを受け取る.
  • 例からネットワーク上の理由でlearnを受信していないop情報.
  • そのうちの1台はインスタンスから新しいprepare要求を送信し、valueはno_op.
  • 新規のprepareリクエストでは、提案IDの数値番号が初期化され、新規の提案者はメインインスタンスよりも大きくなり、インスタンスから新規提案を選択し、空の操作を実行し、relay-logを書き込まない.プライマリ・インスタンスのトランザクションの代わりに、プライマリ・インスタンスGTIDはスレーブ・インスタンスよりも大きい.
  • クラスタネットワーク状態が回復し、新生事物が正常にスレーブインスタンスに同期し、本来の正常同期のGTIDを占有し、クラスタ内のマスターノードがスレーブノードと同じGTIDに対応するトランザクション時と異なるようにする.

  • 結論
    この問題に対して私達も公式にSRを提出して、公式はすでにコミュニティ版MySQL 5.7.26とMySQL 8.0.16の中で修復することができることをフィードバックして、もし企業版の取引先ならば最新のhotfixバージョンを申請することができます.
    MySQLバージョンをアップグレードする前に、このような障害が発生した場合、修復時に手動でチェックし、切り替え時にbinlogのGTID情報と新しいマスターノードに対応するGTIDの情報が一致しているかどうかを確認します.一致しない場合は、一致している場合は、蹴られた元のプライマリノードをクラスタに戻すことができます.
    MGR 5.7.26以前のコミュニティ版を使用しているDBAさんはピットを避けるように注意してください.
    オープンソース分散ミドルウェアDBLE
    コミュニティ公式サイト:https://opensource.actionsky....
    GitHubホームページ:https://github.com/actiontech...
    技術交流グループ:669663113
    オープンソースデータ転送ミドルウェアDTLE
    コミュニティ公式サイト:https://opensource.actionsky....
    GitHubホームページ:https://github.com/actiontech...
    技術交流グループ:852990221