問題の説明ユーザーはプライマリ データベースに対して変更操作を実行しましたが、これには約 1 時間かかりました。操作が完了すると、スレーブ データベースは同期遅延があることを検出しますが、監視チャートの Seconds_Behind_Master インジケーターは 0 を示し、binlog の遅延距離は継続的に増加しています。 原理分析遅延時間を分析しているので、当然、遅延を計算する方法から始めます。便宜上、公式バージョン 5.7.31 のソース コードを引用してここに示します。遅延時間を計算するためのコードを見つけます: ./sql/rpl_slave.cc ブール show_slave_status_send_data(THD *thd, Master_info *mi, char* io_gtid_set_buffer、 char*sql_gtid_set_buffer) の引数 ...... if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) && (!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name()))) { mi->slave_running == MYSQL_SLAVE_RUN_CONNECT の場合 プロトコル->store(0LL); それ以外 プロトコル->store_null(); } それ以外 { 長いtime_diff = ((long)(time(0) - mi->rli->last_master_timestamp) - mi->clock_diff_with_master); protocol->store((longlong)(mi->rli->last_master_timestamp ? 最大値(0L、時間差):0)); } ...... time_diff の計算方法から、この遅延は基本的に時間差であり、その後マスターとスレーブ間の時間差が計算されることがわかります。ただし、if ステートメントが多数あるため、ソース コード ファイル内のコメントを使用します。 /* Seconds_Behind_Master を計算する疑似コード: if (SQL スレッドが実行中) { if (SQL スレッドが利用可能なすべてのリレー ログを処理した場合) { if (IOスレッドが実行中) 0 を印刷します。 それ以外 NULLを印刷します。 } それ以外 Seconds_Behind_Masterを計算します。 } それ以外 NULLを印刷します。 */ Seconds_Behind_Master の計算は 2 つの部分に分かれていることがわかります。
最後に遅延時間を計算するときに、これらの変数の意味を確認します。
遅延を計算する際、実際には、マスター上で再生されたイベントが実行された時刻をスレーブのローカル時刻から減算し、両者の時間差を補正することで値が得られることがわかります。論理的には問題はありません。time(0) と clock_diff_with_master がほとんどの場合にエラーを起こす可能性はないので、今回の問題は last_master_timestamp にあるはずです。 PS: ほとんどの場合は問題ありませんが、time(0) はローカル時間を取得します。そのため、スレーブのローカル時間に問題がある場合は、最終的な値も間違ったものになりますが、今回のケースの範囲ではありません。 次に、イベント実行時に last_master_timestamp を計算するロジックを見つけます。コメントと組み合わせると、通常のレプリケーションと並列レプリケーションでは異なる計算方法が使用されていることがわかります。1 つ目は通常のレプリケーションで、計算時点はイベントの実行前です。 ./sql/rpl_slave.cc ...... もし(もし) { enum_slave_apply_event_and_update_pos_retval exec_res; 列挙型 enum_slave_apply_event_and_update_pos_retval exec_res; ptr_ev = &ev; です。 /* このイベントを実行しなくても、マスタータイムスタンプは保持されます。 マスターの秒数が正しいデルタを示すようにする(イベントがある 再生されないため、遅れを取り続けます。 人工的なイベント、またはリレーログイベント(IOスレッドによって生成されたイベント)の場合 イベント)またはev->whenが0に設定されている場合、またはマスターからのFD、またはハートビート server_id が '0' のイベントの場合、last_master_timestamp は更新されません。 並列実行の場合、last_master_timestampは次の場合にのみ更新されます。 ジョブはGAQから取り出されます。したがって、last_master_timestampが0( GAQが空であることを示し、すべてのスレーブワーカーはイベントを待機しています コーディネーターの場合、最初のタイムスタンプで初期化する必要があります 並行して実行されるイベント。 */ if ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) && !(ev->is_artificial_event() || ev->is_relay_log_event() || (ev->common_header->when.tv_sec == 0) || ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT || ev->server_id == 0)) { rli->last_master_timestamp = ev->common_header->when.tv_sec + (time_t)ev->exec_time; DBUG_ASSERT(rli->last_master_timestamp >= 0); } ...... last_master_timestamp の値は、イベントの開始時刻と実行時刻を足した値です。5.7 では、多くのイベントに実行時刻の値はありませんでした。8.0 では、多くのイベントにこの値が追加されているため、8.0 にアップグレードすることでもたらされたメリットと言えます。 並列レプリケーションの計算方法は次のとおりです。 ./sql/rpl\_スレーブ.cc ...... /* この時点でこれが呼び出されないようにする必要があります cntはゼロです。この値はチェックポイント情報 完全にリセットされます。 */ /* 正しい Seconds_behind_master を報告するために rli->last_master_timestamp を更新します。 GAQ が空の場合はゼロに設定します。 それ以外の場合は、Slave_job_queueの最初のジョブのタイムスタンプで更新します。 これは Log_event::get_slave_worker() 関数で割り当てられました。 */ ts = rli->gaq->空() ? 0 : reinterpret_cast<Slave_job_group*>(rli->gaq->head_queue())->ts; rli->reset_notified_checkpoint(cnt、ts、need_data_lock、true); /* "Coordinator::"commit_positions" の終了 */ ...... コーディネーターの commit_positions ロジックでは、gaq キューが空の場合、last_master_timestamp は直接 0 に設定され、それ以外の場合は gaq キューの最初のジョブのタイムスタンプが選択されます。この計算はリアルタイムではなく、断続的に行われることを付け加えておきます。計算ロジックの前に、次のロジックがあります。 /* 現在、チェックポイント ルーチンは SQL スレッドによって呼び出されています。 そのため、この関数は適切なポイントから呼び出されます SQLスレッドの実行パスで経過時間が計算されます ここで、実行するタイミングを確認します。 */ set_timespec_nsec(&curr_clock, 0); ulonglong diff = diff_timespec(&curr_clock, &rli->last_clock); if (!force && diff < ピリオド) { /* チェックポイントを今すぐ実行する必要はありません。 経過時間が十分ではありません。 */ DBUG_RETURN(偽); } つまり、この期間の時間間隔内では、last_master_timestamp は更新されずに直接返されます。そのため、並列レプリケーションでは、Seconds_Behind_Master の値が時々 0 から 1 に変化することが時々あります。 gaq キューの操作はスタックのプッシュおよびポップ操作に似ているため、gaq に残されたトランザクションは常に未完了のトランザクションです。したがって、一般的なシナリオの観点からは、時間計算は問題ありません。 問題分析原理分析では、全体の計算ロジックを簡単に説明します。それでは、質問自体に戻りましょう。Tencent Cloud Database MySQLでは、デフォルトで並列レプリケーションが有効になっているため、gaqキューが存在し、alter操作に非常に長い時間がかかります。alter操作が並列トランザクションのグループで実行されるかどうかに関係なく(おそらく、DDLは常に別のトランザクショングループです)、gaqキューは最終的に空になり、last_master_timestampは0に設定されます。Seconds_Behind_Masterの計算ロジックを参照すると、最終的なtime_diffも0に設定されるため、alter操作が終了するまでの遅延時間は常に0になります。変更操作が実行されると、gaq キューは新しいイベントとトランザクションでいっぱいになるため、遅延は以前は 0 であったとしても、突然非常に高い値に跳ね上がる可能性があります。 拡大する通常のレプリケーションと並列レプリケーションの計算方法の違いを比較すると、次の特性がわかります。
総括する厳密な遅延判断には、GTIDギャップとbinlog位置ギャップに頼る方が良いでしょう。8.0でのイベント実行時間の変化から判断すると、少なくともOracleの担当者はまだ懸命に取り組んでいます。これらの小さな問題ができるだけ早く修正されることを願っています。 上記は、MySQL 同期遅延が発生したときに Seconds_Behind_Master が 0 のままである理由の詳細な内容です。MySQL 同期遅延 Seconds_Behind_Master が 0 である理由の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
>>: HTMLとリソースがどのように読み込まれるかを理解します
MySQL 組み込みの日付関数 TIMESTAMPDIFF は、2 つの日付間の秒数、分数、時間数、...
jsを使用して、中国語をピンインに変換するパッケージを作成しました。倉庫のアドレスはpinyin-p...
序文: MySQL を使用すると、時間の表示が正しくない、タイムゾーンが GMT+8 ゾーンにない、...
1. MS SQL Server 2005 --1. ログをクリアするexec('DUMP...
目次MySQL 共通関数1. 数値関数文字列関数3. 時間機能4. システム機能5. 集計関数MyS...
導入Docker-Compose プロジェクトは、Docker コンテナ クラスターの迅速なオーケス...
記事のタイトルが「模造虫眼鏡」なのはなぜですか?今日お話ししたいのは、一般的に言われているような、マ...
目次1. ブロックスコープとは何ですか? 2. ブロックスコープが必要なのはなぜですか? 3. 関数...
成果を達成する実装コードhtml <div id="コンテナ"> &...
目次1. 使い方が簡単2. DISTINCTを使用して重複を削除する3. COUNT()の詳細な紹介...
最近、「フットボール ナビゲーション」Web サイトに取り組んでいるときに、上部の固定ナビゲーション...
この記事では、マウスをドラッグしてdivのサイズを調整するJavaScriptの具体的なコードを参考...
目次不変の値とは何ですか?不変の値を使用するのはなぜですか? Reactのパフォーマンス最適化は不変...
目次どうしたの?いつ使うか列挙の数を制御するビット値コントロールインデックス非数値列挙結論はType...
会社から、負荷を実装するためにnginxをベースにFordプロジェクトのWebServiceサーバー...