大量の一時テーブルへの書き込みを伴うレプリケーション

StackOverflow https://stackoverflow.com/questions/116228

  •  02-07-2019
  •  | 
  •  

質問

バックアップの目的で複製する予定のデータベースがあります (現時点ではパフォーマンスは問題ありません)。

レプリケーションを正しく設定し、テストしましたが、すべて問題ありませんでした。

その後、一時テーブルへのすべての書き込みがレプリケートされることに気付きました。つまり、アイドル状態のスレーブでは 1 日分のデータのレプリケーションにほぼ 2 時間かかることになります。

その理由は、データベース内のデータの一部を cronjob 経由で 15 分ごとに再計算して同期を確保しているためです (合計で約 3 分かかるため、Web リクエスト中にこれらの操作を実行することは受け入れられません。代わりに、Web リクエスト中は何も再計算せずに変更を保存するだけで、すべての作業を一括で実行します)。そのデータを効率的に処理するために、(多くの相互依存関係があるため) 一時テーブルを使用します。

ここで、最初の問題は、一時テーブルを使用するトランザクションの処理中にスレーブを再起動すると、一時テーブルが保持されなくなることです。これは一時テーブルを使用しないことで回避できますが、これには独自の問題があります。

さらに深刻な問題は、そのような再計算がなければ、スレーブは 30 分以内に簡単に追いつくことができるということです (再計算は次々に行われるため、15 分ごとにデータを再構築するメリットはありません...)そして文字通り、たとえば 1115 でスタックしているのがわかりますが、すぐに追いついて 1130 などでスタックしてしまいます。

私たちが思いついた解決策の 1 つは、スレーブが再計算を複製しないように、すべての再計算を複製されたデータベースから移動することです。しかし、最終的に更新するテーブルを削除しなければならないという欠点があり、スレーブが事実上「去勢」されてしまいます。実際に使用する前に、すべてを再計算する必要があります。

同様の問題を抱えている人はいますか、またはどのように解決しますか?明らかな何かを見逃しているでしょうか?

役に立ちましたか?

解決

解決策を思いつきました。Nick が言及した replicate-do-db を利用します。誰かが同じような問題を抱えている場合に備えて、ここに書き留めておきます。

この場合、replicate-(wild-)do* オプションだけを使用する場合の問題 (前述したように、中央テーブルを再作成するために一時テーブルを使用します) は、一時テーブルを無視して、中央テーブルにデータを再作成することになります (これにより、最新である中央テーブルに依存するすべてのクエリが異なる結果を生成するため、さらに問題が発生します)。または、同様の問題がある中央テーブルを無視します。言うまでもなく、これらのオプションのいずれかを my.cnf に追加した後は、mysql を再起動する必要があります。私たちは、さらなる再起動を必要とせずに、これらすべてのケース (および将来のケース) をカバーできるものを望んでいました。

そこで、データベースを「実」データベースと「ワークエリア」データベースに分割することにしました。「実際の」データベースのみがレプリケートされます (replicate-wild-do-table 構文に使用するテーブル名の規則を決定できると思います)。

すべての一時テーブルの作業は「ワークエリア」データベースで行われ、上記の依存関係の問題を回避するために、INSERT ... によって中央テーブル (「実際の」データベースにある) にデータを追加しません。SELECT または RENAME TABLE ではなく、tmp テーブルにクエリを実行して、ライブ テーブル上の一種の差分を生成します(つまり、新しい行に対して INSERT ステートメントを生成し、古い行に対して DELETE ステートメントを生成し、必要に応じて更新します)。

このようにして、レプリケートされる唯一のクエリは、まさに必要な更新であり、他には何もありません。15 分ごとに発生する再計算クエリの一部 (ほとんど?) はスレーブに到達することさえできない可能性があり、実行されるクエリは最小限であり、計算コストがまったくかからず、単純な INSERT と DELETE だけです。

他のヒント

MySQL では、5.0 以降、テーブル ワイルドカードを使用して特定のテーブルを複製できるようになりました。設定できるコマンドライン オプションは多数ありますが、MySQL 構成ファイルを介してこれを行うこともできます。

[mysqld]
replicate-do-db    = db1
replicate-do-table = db2.mytbl2
replicate-wild-do-table= database_name.%
replicate-wild-do-table= another_db.%

つまり、指定したテーブル以外のテーブルを複製しないように指示するということです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top