MySQL の基礎となるアーキテクチャの探索: 設計と実装プロセスの概要

画面の前にイケメンがいる場合に備えて、いいね!も必要です。
ここに画像の説明を挿入
著者: Source Code Times の Raymon 氏

前もって言う

Mysql は、広く使用されている優れたデータベース管理システムであり、多くの Java エンジニアにとって日常の開発にほぼ不可欠な部分です。大量のデータを保存する場合でも、データを効率的に取得して管理する場合でも、Mysql は重要な役割を果たします。しかし、日々の開発に Mysql を使用することに加えて、その基礎となるアーキテクチャと設計と実装のプロセスを本当に理解しているのでしょうか? このブログでは、Mysql の基礎となるアーキテクチャの設計と実装プロセスを詳しく説明し、この強力なデータベース システムをより深く理解し、適用できるようにします。Mysql の最下層の謎を一緒に解き明かし、その謎を探っていきましょう。

1. Mysql はあなたの目にはどのように見えますか?

ほとんどの普通の Java エンジニアの目には、MySQL はデータを保存および操作するためのツールとして見られることがよくあります。データの追加、削除、変更、クエリを行うために、データベースの作成、テーブルやインデックスの作成によく使用されます。これらの基本的な使用方法は、日常業務で MySQL を扱う際の日常的な操作になっています。(下の写真のように)ここに画像の説明を挿入

しかし、日常の開発では、MySQL をデータ操作に正しく使用する方法だけに焦点を当てていることが多く、MySQL の基礎となるアーキテクチャと実装原則を深く理解していることはほとんどありません。私たちは、ストレージ エンジン、クエリ オプティマイザー、トランザクション管理などの基礎となるメカニズムについてほとんど知識がなく、パフォーマンスの最適化、データの一貫性の確保、バックアップとリカバリの方法についての知識も限られています。
このため、基礎となる MySQL アーキテクチャの設計と実装プロセスを理解することが非常に重要です。これは、MySQL の内部メカニズムをより完全に理解するのに役立つだけでなく、作業効率と品質も向上します。次のコンテンツでは、MySQL の基礎となるアーキテクチャのさまざまなコンポーネントとテクノロジについて詳しく説明し、MySQL についてより深く包括的な知識を得ることができるようにします。MySQL の根底にあるベールを明らかにし、その謎を探ってみましょう

2. Java システムはどのようにして MySQL に接続しますか?

Java では、通常、MySQL データベースに接続するには JDBC (Java Database Connectivity) が必要です。JDBC は、データベースにアクセスするために Java によって提供される API のセットで、Java コードを通じてさまざまなデータベースと対話できるようにする標準インターフェイスを提供します。

MySQL データベースに接続するには、まず MySQL データベースがシステムにインストールされていること、および適切な MySQL JDBC ドライバーが Java プロジェクトにインポートされていることを確認する必要があります。Mysql ドライバーは、Java システムと Msyql データベースの間にブリッジを構築します。
ここに画像の説明を挿入

したがって、ビジネス コードを実装するときに、関連する SQL ステートメントを実行する必要がある場合、Mysql ドライバーは、SQL ステートメントを Mysql データベースに渡して実行するのに役立ちます。次に、Java システムは、実行するために SQL ステートメントのみに従うことができるかという質問について考えてみましょう
ここに画像の説明を挿入
。データベースは接続を確立しますか? これは絶対に不可能です, なぜなら私たちは真実を理解する必要があるからです. Java で Web システムを開発し, それを Tomcat にデプロイするとします, そのとき Tomcat 自体は複数のリクエストを同時に処理するために複数のスレッドを持たなければなりません. 以下の図を見てみましょう: したがって
ここに画像の説明を挿入
,複数のビジネス リクエストがある場合、次のように、リクエストごとに個別に使用するデータベース接続を確立できます: ただし、同時実行性のここに画像の説明を挿入
高いシナリオでは、各 Tomcat スレッドがデータベースにアクセスする場合、データベースに接続することは可能ですか。 SQL ステートメントを実行し、接続を破棄しますか? このプロセスを頻繁に実行するスレッドが数百ある場合があります。このアプローチはお勧めできません。毎回データベース接続を確立するのに時間がかかり、接続が確立されてSQL文が実行されると接続が切断され、再度接続が行われます。これは非常に非効率的です。

したがって、この問題を解決するには接続プールの概念を導入する必要があります。接続プールは、再利用可能なデータベース接続のセットを維持し、接続を効率的に管理します。Tomcat スレッドはデータベースにアクセスする必要がある場合、接続プールから利用可能な接続を取得し、実行後にその接続を接続プールに返すことができます。これにより、接続の頻繁な作成と破棄が減り、パフォーマンスが向上します。次のように:
ここに画像の説明を挿入

3. MySQL にも接続プールが必要なのはなぜですか?

用事で銀行に行くとき、時には列に並ばなければならないことがあるのをご存知ですか? 銀行員が手続きをしてくれるのを全員が待つ必要があると考えるのは、時間とリソースの無駄ですよね。MySQL 接続プールは銀行取引のキュー システムのようなもので、データベース接続をより効果的に管理および利用するのに役立ちます。
ここに画像の説明を挿入

  1. 接続効率の向上: MySQL では、銀行員が業務を行う前にいくつかの準備を行う必要があるのと同じように、データベース接続を確立するためにいくつかの準備作業が必要です。接続が毎回再作成されると、番号を取得して業務を処理するために誰もが銀行に行って列に並ばなければならないのと同じように、非常に非効率的になります。銀行が業務処理のために事前にいくつかのウィンドウを準備するのと同じように、接続プールは事前にいくつかの接続を作成するため、接続プールから利用可能な接続を 1 つだけ取得できるため、待ち時間が短縮され、接続効率が向上します。

  2. システム リソースの節約: 銀行のスタッフが限られているのと同じように、データベース接続のリソースも限られています。誰もが職員を使って業務を処理すれば、銀行はすぐに麻痺してしまいます。接続プールは、バンク制御ウィンドウの数と同様に、接続の数を管理および制御して、作成される接続が過剰にならないようにすることで、データベースとサーバーのリソースの無駄を回避できます。

  3. 接続管理の簡素化: 銀行のキューイング システムにより銀行員が顧客の業務に集中できるのと同じように、接続プールを使用すると接続をより簡単に管理できるようになります。接続プールを使用すると、手動で接続を作成して解放する必要がなく、接続プールから接続を取得して使用し、完了後に接続プールに戻すだけです。これにより、接続管理の作業が簡素化され、開発効率が向上します。要約すると、MySQL 接続プールは銀行のキュー システムに似ており、接続効率を向上させ、システム リソースを節約し、接続の信頼性を管理し、接続管理を簡素化できます。接続プールは、同時実行性の高いデータベース操作において重要な役割を果たし、MySQL データベースへの接続と対話をより効率的かつ便利に行うのに役立ちます。

4. Mysql は接続リクエストをどのように処理しますか?

Mysql がネットワーク接続リクエストを受信すると、そのリクエストはどのように処理され、最終的に SQL はどのように実行されるのか、プロセス全体のリンクの手順を見てみましょう。
初め:

  1. ネットワーク接続は処理のためにスレッドに割り当てる必要があり、スレッドはリクエストを監視し、ネットワーク接続から Java システムによって送信された SQL ステートメントの読み取りと解析など、リクエスト データを読み取ります
  2. Mysql 内にコンポーネントが提供されます: SQL インターフェイス (SQL インターフェイス)。特に SQL ステートメントを実行するために使用されます。
  3. 次に、クエリ オプティマイザーを使用します。実行する最適なクエリ パスを選択します。機能: 数十行、数百行、さらには数千行で作成された複雑な SQL ステートメントのクエリ パス ツリーを生成し、そこから最適なクエリを選択します。抜け道。
  4. エグゼキューターの呼び出し: 実行計画に従ってストレージ エンジンのインターフェイスを呼び出します。
  5. 実際に SQL ステートメントを実行するためにストレージ エンジン インターフェイスを呼び出します 機能: エグゼキューターは、オプティマイザーによって選択された実行プランに従って、特定の順序とステップに従ってストレージ エンジン インターフェイスを呼び出し、SQL ステートメントのロジックを実行します
  6. ストレージ エンジン: データの管理と保存、InnoDB、MyISAM、メモリなどのさまざまなストレージ エンジンのサポート。特定の SQL ステートメントの実行を担当するストレージ エンジンを選択できるようになりました。現在、MySQL は通常、デフォルトで InnoDB ストレージ エンジンを使用します。

ここに画像の説明を挿入
上記の実行プロセス全体に興味がある場合は、詳しく調べることができます。この記事では詳細は紹介しません。InnoDB ストレージ エンジンがデータをどのように管理および保存するかを分析してみましょう。

5. InnoDB の重要なメモリ構造: バッファー プール

InnoDB ストレージ エンジンでは、メモリ内にバッファ プール (BufferPool) という非常に重要なコンポーネントがあり、大量のデータをキャッシュします。そのため、後でクエリを実行するときに、メモリ バッファ プールにデータがある場合、ディスクをチェックする必要はありません。下の図を見てみましょう。
ここに画像の説明を挿入
たとえば、SQL ステートメント: update users set name='xxx' where id=1、たとえば、データ「id=1」の行については、まずデータ「id=1」の行が存在するかどうかを確認します。バッファ プール (存在しない場合) は、ディスクからバッファ プールに直接ロードされ、このレコード行に排他ロックが追加されます。

バッファ プールは、LRU (Least Recent Used) アルゴリズムを使用してメモリ内のデータ ページを管理します。クエリがデータにアクセスする必要がある場合、InnoDB はまず、対応するデータ ページがバッファ プールに存在するかどうかを確認します。存在する場合、ディスクから読み取るのではなくメモリから直接データをフェッチするため、クエリのパフォーマンスが大幅に向上します。データ ページがバッファ プールにない場合、InnoDB はデータ ページをバッファ プールに読み取り、後続のクエリのためにメモリ内に保持します。

バッファー プールのサイズを適切に構成すると、頻繁に使用されるデータ ページを常にメモリ内に保持できるため、クエリの効率が向上します。一般に、より大きなバッファ プールは、大量のメモリを搭載したサーバーに適しています。

6.undo ログ ファイル: 更新されたデータをロールバックできるようにする

Undo ログ ファイルは、データベース内で進行中のトランザクションの操作を記録し、トランザクションをロールバックする必要があるときにロールバック データを提供するために使用されます。更新、削除、または挿入操作が発生すると、InnoDB エンジンは関連情報を Undo ログ ファイルに記録します。

トランザクションを元に戻す必要がある場合、InnoDB エンジンは Undo ログを使用してデータをトランザクション開始前の状態に復元します。操作を逆に行うことでデータへの変更を元に戻し、データを以前の状態に復元します。
ここに画像の説明を挿入
更新するレコードをディスクファイルからバッファプールにロードし、同時にロックし、更新前の古い値をアンドゥログファイルに書き込むと、正式にレコードの更新を開始できます。バッファプール内のレコードが最初に更新され、このときのデータはダーティデータです。

ここでのいわゆるメモリ バッファ プール内のデータの更新とは、メモリ内のデータの "id=1" 行の name フィールドを
"xxx" に変更することを意味します。
ここに画像の説明を挿入

7. REDO ログ ファイル: データの一貫性と永続性を確保します。

ここで、上図の変更操作がキャッシュに書き込まれたが、将来の永続化のためにディスクに同期されていない場合を想像してみましょう。この時点で、msyql マシンがダウンしてハングアップし、データがキャッシュ内のキャッシュが失われると、更新されたデータも失われます。したがって、Mysql データの一貫性と耐久性を確保するために、innodb エンジンは REDO ログ ファイルを導入します。

REDO ログは、主にトランザクションがコミットされる前にデータベースに対して実行された変更操作を記録するために使用される物理ログです。データベースがクラッシュまたは失敗した場合、REDO ログを使用して最後に送信された状態に復元し、データの永続性を確保できます。

REDO ログの役割は主に次の 2 つの側面に反映されます。

  1. データ回復: データベースに障害が発生した場合、コミットされていない変更操作を REDO ログを通じてデータベースに再適用することで、最後に送信された状態に復元できます。
  2. パフォーマンスの向上: 変更操作を REDO ログに記録することにより、ディスク IO 操作をシーケンシャル書き込み操作に変換でき、データベースの書き込みパフォーマンスが大幅に向上します。

したがって、更新操作が実行されると、Mysql はメモリへの変更を REDO ログ バッファに書き込みます。これはメモリ内のバッファでもあり、REDO ログを保存するために使用されます。いわゆるREDOログとは、レコード「id=10」のnameフィールドの値をxxxに変更するなど、データにどのような変更を加えたかを記録するもので、これはログです。以下の図に示すように:
ここに画像の説明を挿入
備考: innodb_log_buffer_size: REDO ログのバッファ サイズを指定します。デフォルトは 8MB です。値を大きくすると、
頻繁な更新操作が減り、パフォーマンスが向上しますが、使用するメモリも多くなります。

8. トランザクションを送信します: REDO ログのフラッシュ

トランザクションがコミットされると、REDOLOG のキャッシュ領域のデータがディスクにフラッシュされます。では、この時点でデータ損失は問題になるのでしょうか?

実際、更新ステートメントのトランザクションを送信しなかった場合は、トランザクションが正常に実行されなかったことを意味するため、問題ではありません。この時点では、MySQL のダウンタイムによりメモリ内のすべてのデータが失われていましたが、ディスク上のデータがまだ元の状態であることがわかります。

REDO ログをディスクに書き込むための 3 つの戦略

フラッシュ戦略は innodb_flush_log_at_trx_commit を通じて構成されます。これにはいくつかのオプションがあります。

  1. パラメータ値が 0 の場合、REDO ログはディスクに書き込まれません。これは、REDO ログがディスクにフラッシュされないこと、つまり、非同期書き込み戦略を意味します。トランザクションがコミットされると、REDO ログの変更操作はオペレーティング システムのページ キャッシュにのみ書き込まれ、すぐにはディスクにフラッシュされません。これにより、最高の書き込みパフォーマンスが得られますが、データベースのクラッシュまたは障害が発生した場合には、ある程度のデータ損失が発生する可能性があります。
  2. パラメータ値は 1 で、REDO ログがディスクに送信されます [デフォルト値] は、REDO ログが同期的にディスクにフラッシュされることを意味します。トランザクションがコミットされると、REDO ログの変更操作がすぐにディスクに書き込まれ、IO 操作の完了を待ちます。データの永続性を確保すると同時に、パフォーマンスにも一定の影響を与えます。これは最も一般的に使用される設定であり、ほとんどのアプリケーション シナリオに適しています。

ここに画像の説明を挿入

  1. パラメータ値は 2 で、REDO ログは OS キャッシュに入力されます。

トランザクションがコミットされるたびに REDO ログの変更操作がディスクに書き込まれますが、IO 操作の完了は待機しないことを示します。トランザクションがコミットされると、まず REDO ログがオペレーティング システムのページ キャッシュに書き込まれ、次にバックグラウンド スレッドがデータをディスクに非同期的にフラッシュします。この設定では、パフォーマンスが向上し、ある程度のデータ保護が提供されますが、依然としていくつかのリスクがあります。
ここに画像の説明を挿入
フラッシュ戦略の選択
適切な innodb_flush_log_at_trx_commit 値の選択は、データの永続性とパフォーマンスの要件によって異なります。データの永続性要件が非常に高い場合は、1 に設定できます。パフォーマンス要件が高く、ある程度のデータ損失が許容される場合は、0 に設定できます。ある程度のデータ保護を確保しながらパフォーマンスの向上を追求する場合は、2 に設定することもできます。

MySQL 構成ファイルのパラメータ設定を変更することで innodb_flush_log_at_trx_commit 値を調整し、MySQL サービスを再起動してそれを有効にすることができます。

通常は 1 に設定することをお勧めします。つまり、トランザクションをコミットするときに、REDO ログをディスク ファイルにフラッシュする必要があります。これにより、行ったすべての変更を復元するための REDO ログがディスク ファイルに存在するため、トランザクションのコミット後にデータが失われることがないことが厳密に保証されます。

9. binlog とは正確には何ですか

実は先ほどのREDOログというのは、「どのデータページのどのレコードにどのような変更が加えられたか」というようなことを記録するもので、物理性に偏ったREDOログの一種です。

また、REDO ログ自体は InnoDB ストレージ エンジンに固有のものです。binlog はアーカイブ ログと呼ばれ、「users テーブルの id=1 のデータ行を更新します。更新後の値は何ですか」のような、ロジックに偏ったログを記録します。binlog は InnoDB ストレージではありません。エンジン固有のログ ファイルは、mysql サーバー自体に属するログ ファイルです。したがって、トランザクションが送信されると、同時に binlog が書き込まれます: ここに画像の説明を挿入
binlog ログのフラッシュ戦略の分析
binlog ログの場合、実際にはさまざまなフラッシュ戦略があり、binlog のフラッシュ戦略を制御できる sync_binlog パラメータとそのデフォルト値が存在します。値が 0 の場合、バイナリログをディスクに書き込むと、バイナリログはディスクファイルに直接入力されず、OS キャッシュメモリキャッシュに入ります。したがって、前の分析と同じように、この時点でマシンがダウンしている場合、OS キャッシュ内の binlog ログは失われます。sync_binlog パラメーターを
ここに画像の説明を挿入
1 に設定すると、この時点でトランザクションの送信が強制されます。バイナリログはディスクファイルに直接書き込まれるため、この方法でトランザクションがコミットされた後は、たとえマシンがダウンしても、ディスク上のバイナリログは失われません。

binlog と redo ログに基づいてトランザクションの送信を完了する

バイナリ ログをディスク ファイルに書き込むと、最終的なトランザクションの送信が完了します。このとき、この更新に対応するバイナリ ファイルの名前と、ファイル内の更新されたバイナリ ログの場所が REDO ログに書き込まれます。ログ ファイルに移動し、同時に REDO ログ ログ ファイルにコミット マークを書き込みます。この事項が完了すると、いよいよトランザクションの投入が完了しますが、
ここに画像の説明を挿入
最後のステップでREDOログにコミットマークを書き込む意味は何でしょうか?

REDO ログと binlog ログの一貫性を保つには、最後のトランザクション コミット マークを REDO ログに書き込む必要があります。その後、トランザクションはこの時点で正常にコミットされ、REDO ログにはこの更新に対応するログが存在します。 binlog のログでもあります。2 回目の更新に対応するログ、REDO ログ、binlog は完全に一致しています。

バックグラウンド IO スレッドは、ディスクへのメモリ更新後にダーティ データをランダムにフラッシュします。

MySQL にはバックグラウンド IO スレッドがあり、将来の特定の時点で、メモリ バッファ プール内の変更されたダーティ データをディスク上のデータ ファイルにランダムにフラッシュします。次の図を見てみましょう
ここに画像の説明を挿入
。データをディスクに戻すと、mysql がクラッシュしたとしても問題ありません。再起動後、REDO ログに従って以前に送信されたトランザクションによって行われた変更がメモリに復元され、適切なタイミングで IO が実行されるまで待機します。スレッドは自然にこの変更を行います。最終データはディスク上のデータ ファイルにフラッシュされます。

10. まとめ

InnoDB ストレージ エンジンには、主にバッファ プールや REDO ログ バッファなどのメモリ内のいくつかのキャッシュ データが含まれており、また、いくつかの UNDO ログ ファイル、REDO ログ ファイルなども含まれており、mysql サーバー自体にも binlog ログ ファイルがあります。

更新を実行すると、各 SQL ステートメントはバッファ プール内のキャッシュ データの変更、UNDO ログの書き込み、REDO ログ バッファの書き込みに対応しますが、トランザクションを送信すると、REDO ログは確実にディスクにフラッシュされます。 、ビンログがディスクにフラッシュされ、REDO ログ内のトランザクション コミット マークが完了し、最後に、バックグラウンド IO スレッドがバッファ プール内のダーティ データをディスクにランダムにフラッシュします。

記事の最後には、画面の前にイケメンがいる場合に備えて、「いいね!」が必要です。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/u014494148/article/details/131909510