MySQL で binlog を使用する際のフォーマットの選択方法

MySQL で binlog を使用する際のフォーマットの選択方法

1. binlogの3つのモード

1.ステートメントレベルモード

データを変更するすべての SQL ステートメントは、マスターの bin-log に記録されます。スレーブがレプリケーションしている場合、SQL プロセスはそれを元のマスターによって実行されたのと同じ SQL に解析し、再度実行します。

利点: ステートメント レベルでの利点は、まず行レベルでの欠点を解決します。各データ行の変更を記録する必要がないため、bin-log ログの量が削減され、IO が節約され、パフォーマンスが向上します。マスター上で実行されたステートメントの詳細と、ステートメントが実行されたときのコンテキスト情報のみを記録する必要があるためです。

デメリット: 実行ステートメントを記録するため、これらのステートメントをスレーブ側で正しく実行するには、実行時に各ステートメントの関連情報、つまりコンテキスト情報も記録して、すべてのステートメントがスレーブ側で実行されたときにマスター側で実行されたときと同じ結果が得られるようにする必要があります。さらに、MySQL の急速な発展により、多くの新機能が追加され、MySQL レプリケーションにかなりの課題をもたらしました。当然、レプリケーションに関係するコンテンツが複雑になるほど、バグが発生する可能性が高くなります。ステートメント レベルでは、MySQL レプリケーションの問題を引き起こす状況が多数見つかりました。これらの問題は主に、データの変更時に特定の関数または機能を使用した場合に発生します。たとえば、一部のバージョンでは sleep() を正しくレプリケートできません。

2. 行レベルモード

ログには変更されたデータの各行が記録され、スレーブ側で同じデータが変更されます。

利点: Bin-log では、実行された SQL ステートメントのコンテキスト関連の情報を記録する必要はありません。どのレコードが変更され、どのように変更されたかを記録するだけで済みます。したがって、行レベルのログの内容には、データ変更の各行の詳細が明確に記録されます。さらに、特定の状況でストアド プロシージャ、関数、またはトリガーの呼び出しとトリガーが正しく複製されないという問題も発生しません。

デメリット: 行レベルでは、実行されたすべてのステートメントがログに記録されると、各行への変更として記録されます。これにより、大量のログ コンテンツが生成される場合があります。たとえば、update product set owner_member_id='d' where owner_member_id='a' のような更新ステートメントがあります。実行後、ログにはこの更新ステートメントに対応するイベントは記録されません (MySQL は、イベントの形式で bin-log ログを記録します)。ただし、このステートメントによって更新された各レコードの変更は記録されます。このように、更新される多くのレコードの多くのイベントが記録されます。当然、bin-log ログの量は非常に多くなります。

3. 混合モード

実際、これは最初の 2 つのモードの組み合わせです。混合モードでは、MySQL は実行された特定の SQL ステートメントごとにログ形式を区別し、ステートメントと行のどちらかを選択します。新しいバージョンのステートメント レベルは以前と同じで、実行されたステートメントのみが記録されます。 MySQL の新しいバージョンでは、行レベル モードが最適化されています。すべての変更が行レベルで記録されるわけではありません。たとえば、テーブル構造が変更されると、ステートメント モードで記録されます。SQL ステートメントが実際にデータを変更する更新ステートメントまたは削除ステートメントである場合、すべての行の変更は引き続き記録されます。

2. binlog を使用する場合、どのような形式を選択すればよいですか?

上記の紹介から、binlog_format=STATEMENT は、いくつかのシナリオで IO を節約し、同期を高速化できることがわかります。ただし、InnoDB などのトランザクション エンジンの場合、分離レベルが READ-COMMITTED および READ-UNCOMMITTED の場合、またはパラメータ innodb_locks_unsafe_for_binlog が ON の場合、binlog_format=statement での書き込みは禁止されます。同時に、非トランザクション エンジンおよびその他の分離レベルのデフォルトの書き込みステートメント形式である binlog_format=mixed では、行形式のみが記録されます。

> @@tx_isolation を選択します。
+----------------+
| @@tx_isolation |
+----------------+
| コミット読み取り |
+----------------+

> テーブル t(c1 int) を作成します。engine=innodb;

> binlog_format=ステートメントを設定します。

> t値に挿​​入(1);
エラー 1665 (HY000): ステートメントを実行できません。BINLOG_FORMAT = STATEMENT であり、少なくとも 1 つのテーブルが行ベースのログ記録に制限されているストレージ エンジンを使用しているため、バイナリ ログに書き込むことができません。トランザクション分離レベルが READ COMMITTED または READ UNCOMMITTED の場合、InnoDB は行ログ記録に制限されます。

> binlog_format='mixed' を設定します。

> 'mysql-bin.000004' の binlog イベントを表示\G
************************** 3. 行 ****************************
 ログ名: mysql-bin.000002
  順位: 287
 イベントタイプ: Gtid
 サーバーID: 3258621899
終了ログ位置: 335
  情報: SET @@SESSION.GTID_NEXT= 'ed0eab2f-dfb0-11e7-8ad8-a0d3c1f20ae4:9375'
************************** 4. 行 ****************************
 ログ名: mysql-bin.000002
  ポジション: 335
 イベントタイプ: クエリ
 サーバーID: 3258621899
終了ログ位置: 407
  情報: 開始
************************** 5. 行 ****************************
 ログ名: mysql-bin.000002
  ポジション: 407
 イベントタイプ: テーブルマップ
 サーバーID: 3258621899
終了ログ位置: 452
  情報: table_id: 124 (test.t)
************************** 6. 行 ****************************
 ログ名: mysql-bin.000002
  ポジション: 452
 イベントタイプ: Write_rows_v1
 サーバーID: 3258621899
終了ログ位置: 498
  情報: table_id: 124 フラグ: STMT_END_F
************************** 7. 行 ****************************
 ログ名: mysql-bin.000002
  ポジション: 498
 イベントタイプ: Xid
 サーバーID: 3258621899
終了ログ位置: 529
  情報: COMMIT /* xid=18422 */

ステートメント形式の binlog を READ-COMMITTED (RC) モードと READ-UNCOMMITTED モードで使用できないのはなぜですか?これは、ステートメントがトランザクション内で実行されると、他のトランザクションによってコミットされたデータや書き込まれたデータが確認できるためです。トランザクションがコミットされた後、バイナリログが書き込まれます。その後、スレーブでそれを再生すると、表示されるデータはマスターに書き込まれたときと一致しなくなります。

例えば:

表があります:

+------+------+
| ア | ロ |
+------+------+
| 10 | 2 |
| 20 | 1 |
+------+------+

私たちは次のことを行います:

  1. セッション1はトランザクションで更新を実行します。UPDATE t1 SET a=11 where b=2; 行(10,2)のレコードは条件を満たしていますが、コミットされません。
  2. セッション2も更新操作を実行し、行(20,1)を(20,2)に更新して更新をコミットします。
  3. 次に、前のセッション1が行(10,2)への更新をコミットします。

binlog が Statement 形式で記録されている場合、スレーブがデータを再生すると、最初に送信されたセッション 2 の更新が最初に再生され、行 (20,1) が (20,2) に更新されます。次に、セッション 1 でステートメント UPDATE t1 SET a=11 where b=2; を再生すると、2 つの行 (10,2) と (20,2) が (11,2) に更新されます。この結果、マスターデータベースの動作は (11, 2)、(20,2) となり、スレーブ側の動作は (11,2)、(11, 2) となります。

3. 問題分析

上記を具体的な例で説明します。根本的な理由は、RC トランザクション分離レベルがトランザクションのシリアル化実行要件を満たしておらず、非反復読み取りとファントム読み取りを解決できないことです。

Repetable-Read および Serializable 分離​​レベルの場合、ステートメントの形式が記録されるため、問題にはなりません。これは、RR および Serializable の場合、繰り返し読み取りが保証されるためです。更新を実行すると、該当する行をロックするだけでなく、条件を満たす行が挿入される可能性がある場合に GAP ロックが追加されます。上記の場合、セッション 1 が b = 2 で行を更新すると、すべての行と範囲がロックされるため、セッション 2 は更新時に待機する必要があります。分離レベルの観点から見ると、Serializable はトランザクションのシリアル化を満たすため、binlog シリアル レコード トランザクション ステートメント形式は受け入れられます。同時に、InnoDB の RR 分離レベルは、非反復読み取りとファントム読み取りを実際に解決し、ANSI SQL 標準のトランザクション分離要件を満たしています。

READ-COMMITTED および READ-UNCOMMITTED binlog_format の制限は、すべてのトランザクション エンジンに適用されます。

4. コンテンツを拡張する

InnoDB RR および Serializable 分離​​レベルでは、binlog レコード ステートメント形式が保証されますか?必ずしもそうではありません。 Innodb には、GAP ロックを制御するためのパラメータ innodb_locks_unsafe_for_binlog があります。デフォルト設定は OFF です。

mysql> 'innodb_locks_unsafe_for_binlog' のような変数を表示します。
+--------------------------------+-------+
| 変数名 | 値 |
+--------------------------------+-------+
| innodb_locks_unsafe_for_binlog | オフ |
+--------------------------------+-------+
セット内の1行(0.01秒)

つまり、RR レベル以上では、行ロックに加えて GAP ロックも適用されます。ただし、このパラメータを ON に設定すると、GAP ロックは現在の読み取りに追加されません。つまり、RR 分離レベルで Next-key ロックを必要とする現在の読み取りは、READ-COMMITTED に縮退します。したがって、このパラメータを ON に設定すると、使用されるトランザクション分離レベルが Repetable-Read であっても、スレーブ データの正確性は保証されません。

V. 結論

オンライン業務で、InnoDB などのトランザクション エンジンを使用する場合、RR 分離レベル以上の書き込みを保証する場合を除き、binlog_format を STATEMENT に設定しないでください。そうしないと、業務の書き込みができなくなります。混合モードの binlog_format の場合、RR 分離レベル以下のこれらのトランザクション エンジンは ROW イベントも書き込む必要があります。

MySQL で binlog を使用する際のフォーマットの選択方法についての記事はこれで終わりです。MySQL で binlog を使用する際のフォーマットの選択方法についての詳細は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL シリーズ: redo ログ、undo ログ、binlog の詳細な説明
  • MySQL binlog_ignore_dbパラメータの具体的な使用法
  • MySQLを監視するためのbinlogログ解析ツールの詳しい説明:Canal
  • MySQL 8.0 の binlog の詳細な説明
  • MYSQL の binlog 最適化に関する考察の要約
  • MySQLデータベースのbinlogクリーンアップコマンドの詳細な説明
  • MySQLデータベース監視binlogを有効にする手順
  • MySQL の innodb_flush_log_at_trx_commit と sync_binlog を区別する方法

<<:  VueはExcelデータをエクスポートするパブリック関数メソッドをカプセル化します

>>:  nginxリバースプロキシを使用するときに長時間接続を維持する方法

推薦する

MySQLデータベースを誤って削除した後にデータを回復するための手順

日々の運用・保守作業において、MySQL データベースのバックアップは重要です。ウェブサイトにとって...

DockerはホストのMysql操作に接続します

今日、会社のプロジェクトでは docker を設定する必要があります。Windows に正常にインス...

丸い角や鋭い角の代わりに文字を使用することに関する研究経験の共有

1. フォントと文字表示の関係左側と右側の鋭角部分は Songti フォントで表示されます: &l...

Dockerでコンテナを作成するときのディレクトリ権限

昨日プロジェクトを書いていた時に、MySQL の派生版である Percona を使う必要があったので...

MySQL で日付を保存するためのベスト プラクティス ガイド

目次序文時間型を保存するのに文字列を使用しないでくださいMySQL の日付型日時タイムスタンプTIM...

CentOS 7 は Hadoop 2.10 の高可用性 (HA) をビルドします

この記事では、CentOS 7 で高可用性 Hadoop 2.10 クラスターを構築する方法を紹介し...

vue 動的コンポーネント

目次1. コンポーネント2. キープアライブ2.1 問題点2.2 キープアライブを使って解決する2....

Linux運用保守ツールSupervisor(プロセス管理ツール)のインストールと使用

1. はじめにSupervisor は Python で開発された汎用プロセス管理プログラムです。通...

Linux ファイアウォールの状態確認方法の例

Linuxファイアウォールの状態を確認する方法1. 基本操作 # ファイアウォールのステータスを表示...

HTML ファイルにフラッシュ ビデオ形式 (flv、swf) ファイルを埋め込む方法

Flash ファイル形式: .FLV および .SWFフラッシュ ビデオ形式には、.flv と .s...

メンテナンス可能なJSコードの書き方を教えます

目次保守可能なコードとは何ですか?コード規約1. 読みやすさ2. 変数と関数の命名3. 透過的な変数...

MySQL でテーブルスペースの断片化を解消する詳細な例

MySQL でテーブルスペースの断片化を解消する詳細な例断片化の原因(1)テーブルのストレージは断片...

MySQL データベース開発仕様 [推奨]

最近、問題のある新しい SQL が本番データベースに入力される数を最小限に抑えるために、開発仕様を整...

CentOS システムでの JDK のインストールと設定の概要

目次序文OpenJDKの確認とアンインストールダウンロードした圧縮パッケージを使用してJDKをインス...

Win7 での Mysql 5.7.17 winx64 インストール チュートリアル

ソフトウェア バージョンとプラットフォーム: MySQL-5.7.17-winx64、win7 Ho...