MySQLデータベースのバッファプールの原則は何ですか?多分それを読んだ後にあなたは理解するでしょう

序文

インタビュアー:クラスメート、Mysqlキャッシュプールについて話していただけますか?

それはCPPです:ああ、それはとても難しいですか、言語を整理させてください。(内部OS:このTMは簡単ではありませんか?私はあなたに30分を与えることができます!)

インタビュアー:はい、少し考えてみてください。

.... 1分後...

それはCPPです:私は準備ができています、あなたは聞くことができます、私は演技を始めようとしています。

 

なぜバッファプールがあるのですか?

MySQLのinnodbストレージエンジンはディスクストレージに基づいており、ページ方式で管理されます。

データベースシステムでは、CPU速度とディスク速度のギャップが非常に大きいため、ギャップを最大限に埋めるために、バッファプールの概念を提案します。

したがって、バッファプールは、簡単に言うと、メモリ速度を使用してディスク速度の低下を補う「メモリ領域」であり、データベースのパフォーマンスに影響を与えます。

バッファプールの基本原理

「読み取り操作」

データベース内のページを読み取るには、まずディスクから読み取ったページをバッファプールに保存します。次回同じページを読み取るときは、最初にそのページがバッファプールにあるかどうかを確認します。

そうである場合、ページがバッファプールでヒットしたと言われ、ページは直接読み取られます。そうでない場合、ディスク上のページは引き続き読み取られます。

「書き込み操作」

データベースでのページ変更操作の場合、キャッシュプール内のページは最初に変更され、次に特定の頻度でディスクに更新されます。ページが変更されるたびにディスクに更新されるわけではありませんが、ページは次の方法でディスクに更新されます。チェックポイントメカニズム。

読み取り操作であろうと書き込み操作であろうと、ディスク上で直接ではなく、バッファプール上での操作であることがわかります。

バッファプール構造

バッファプールは連続したメモリスペースであり、innodbストレージエンジンはページを介してこのメ​​モリを管理します。

バッファプールの構造は次のとおりです。

 

キャッシュプールには、データページ、インデックスページ、挿入キャッシュ、アダプティブハッシュインデックス、ロック情報、およびデータフィールドが含まれていることがわかります。

データページとインデックスページはほとんどのメモリを使用します。

「しかし、InnoDBはどのようにしてバッファプール内の非常に多くのページを管理するのでしょうか?」

これらのキャッシュされたページをより適切に管理するために、innodbは、キャッシュされたページごとにいわゆる制御情報を作成します。これらの制御情報には、次のページが含まれます。

  • 表スペース番号(sapce id)
  • 页号(ページ番号)
  • バッファプール内のページアドレス
  • 一部のロック情報とLSN情報のログシーケンス番号
  • その他の管理情報

各キャッシュページに対応する制御情報が占めるメモリサイズは同じです。各ページに対応する制御情報が占めるメモリを「制御ブロック」と呼びます

「制御ブロック」とキャッシュページは1対1で対応しており、すべてバッファプールに格納されています。制御ブロックはバッファプールの前面に格納され、キャッシュページはバッファの背面に格納されています。プール。

バッファプールに対応するメモリ空間の概略図:

 

バッファプールパラメータ設定

  • innodb_buffer_pool_size:バッファープールのサイズは、最大で物理メモリの80%に設定する必要があります
  • innodb_buffer_pool_instance:設定されているバッファープールの数。通常は、バッファープールの数をCPUの数に設定することをお勧めします。複数のバッファープールを使用すると、データベース内のリソースの競合を減らし、データベースの同時アクセス機能を向上させることができます。
  • innodb_old_blocks_pct:LRU全体に対する旧世代のチェーン長の比率。デフォルトは3:7です。
  • innodb_old_blocks_time:古い世代の滞在時間ウィンドウ(ミリ秒単位)。デフォルトは1000です。つまり、「訪問済み」と「古い世代に滞在」の両方の条件が1を超えると、新しい世代の先頭に挿入されます。 2番目」

キャッシュプール管理

「バッファプールが依存するリンクリスト構造を管理する」:

無料のリンクリスト

Mysqlサーバーを起動するときは、バッファープールの初期化プロセスを完了する必要があります。つまり、バッファープールのメモリスペースを割り当て、それを制御ブロックとキャッシュページのいくつかのペアに分割しますが、現時点では実ディスクはありません。ページはバッファプールにキャッシュされます。その後、プログラムの実行中、ディスク上のページは引き続きバッファプールにキャッシュされます。

使用の過程で、使用可能なキャッシュページを記録するために、すべての空きページをノードにパックしてリンクリストを作成します。このリンクリストは、無料リンクリスト(無料リンクリスト)と呼ばれます。初期化が完了したばかりのバッファプール内のすべてのキャッシュページは空きであるため、各キャッシュページは[空き]リンクリストに追加されます。

無料リンクリストの管理を容易にするために、このリンクリストに対していくつかの「制御情報」が具体的に定義されています。これには、ヘッドノードアドレス、テールノードアドレス、現在のリンクリスト内のノード数などの情報が含まれます。 。

さらに、「キャッシュページ制御ブロック」のアドレスはフリーリンクリストの各ノードに記録され、各「キャッシュページ制御ブロック」は対応する「キャッシュページアドレス」を記録するため、各フリーリンクリストと同等です。リストノードは、空きキャッシュページに対応します。

全員の構造図を描きます。

 

この写真はどうですか、今あなたはそれを理解することができます!

2.Lruリンクリスト

Lruリンクリストは、読み取られたページを管理するために使用されます。データベースが起動したばかりの場合、Lruリンクリストは空です。このとき、ページも空きリストに配置されます。データを読み取る必要がある場合は、無料リンクリストからページが要求されます。ディスクから読み取ったデータを要求されたページに配置します。このページのコレクションをLruリンクリストと呼びます。

3.リンクリストをフラッシュします

フラッシュリンクリストは、変更されたページを管理するために使用されます。バッファプール内の変更されたページは、「ダーティページ」とも呼ばれます。ダーティページは、Lruリンクリストとフラッシュリンクリストの両方に存在します。フラッシュリンクリストには、ポインタAが含まれます。 Lruリンクリスト内の特定のデータへのポインタ。

したがって、Lruリンクリストのページが初めて変更された場合にのみ、対応するポインタがフラッシュに保存されます。後でページが変更された場合、Lruリンクリストのページに対応するデータが直接更新されます。

これら3つの間にそのような関係があります:

 

読み取り操作

バッファプールの最も重要な機能の1つは、「高速読み取り」です。読み取りの高速化とは、データページにアクセスする必要がある場合です。ページが既にバッファープールにある場合は、ディスクにアクセスする必要はなく、ページのコンテンツをバッファープールから直接取得できます。ページ内のデータにアクセスする必要がある場合は、ページをバッファプールにロードします。ページがすでにバッファプールにある場合は、直接使用できます。

質問:バッファプール内のページをすばやく見つける方法は?

データページをクエリするときにLruをスキャンしないようにするために、ページは実際にはテーブルスペース番号+ページ番号に基づいて配置されます。

これは、テーブルスペース番号+ページ番号がキーであり、キャッシュページが対応する値であることに相当します。

ハッシュテーブルを作成するには、テーブルスペース番号+ページ番号をキーとして、キャッシュページを値として使用します。特定のページのデータにアクセスする必要がある場合は、最初にテーブルスペース番号に従って対応するキャッシュがあるかどうかを確認します。 +ハッシュテーブルページのページ番号。

その場合は、キャッシュページを直接使用してください。

そうでない場合は、[空き]リンクリストから空きキャッシュページを選択し、ディスク内の対応するページをキャッシュページの場所にロードします。

ページをディスクからバッファプールにロードする必要があるときはいつでも、空きキャッシュページが空きリンクリストから取得され、キャッシュページに対応する制御ブロックの情報が入力され、次に対応する空きリンクリストが入力されます。キャッシュページへノードがリンクリストから削除され、キャッシュページが使用されたことを示し、ページがLruリンクリストに書き込まれます。

初期化時、バッファプール内のすべてのページは空きページです。データを読み取る必要がある場合、ページは空きリンクリストから要求されますが、物理メモリを無制限に増やすことはできませんが、データベース内のデータは常に増加しています。 、そのため、無料リンクリストのページが使い果たされます。

したがって、バッファプールからキャッシュされたページの一部を削除することを検討する必要があります。次に、削除する方法と、削除されるキャッシュされたページを検討する必要があります。合計nページがアクセスされると仮定すると、アクセスされたページがキャッシュ内にある回数をnで割った値がキャッシュヒット率です。キャッシュヒット率が高いほど、ディスクとのIOの相互作用は少なくなります。

キャッシュヒット率を向上させるために、InnoDBは従来のLruアルゴリズムを最適化して、次の2つの問題を解決しました。1。事前読み取りの無効化2.バッファープールの汚染

書き込み操作

バッファプールのもう1つの主な機能は、「書き込みの高速化」です。つまり、ページを変更する必要がある場合、ページは最初にバッファプールで変更され、このページが変更された場合でも、関連するREDOログが記録されます。完了しました。

変更されたページは実際にディスクに更新されます。これはバックグラウンド更新スレッドによって行われます。前のページの更新は最初にキャッシュプールで実行され、次にディスク上のページと矛盾します。このようなキャッシュページはダーティページ(ダーティページ)と呼ばれます。

質問:これらの変更されたページはいつディスクにフラッシュされますか?どのような順序でディスクにフラッシュしますか?

最も簡単な方法は、変更が発生するたびにディスク上の対応するページにすぐに同期することですが、ディスクにデータを頻繁に書き込むと、プログラムのパフォーマンスに深刻な影響を及ぼします。したがって、キャッシュページが変更されるたびに、変更をディスクにすぐに同期することはできませんが、同期は将来の特定の時点で実行され、バックグラウンド更新スレッドが順番にディスクにフラッシュして変更を実行します。ディスクに着陸します。

しかし、ディスクにすぐに同期しない場合、バッファプール内のどのページがダーティページであり、後で同期するときにどのページが変更されていないかを判断するにはどうすればよいですか?

InnoDBは、キャッシュされたすべてのページを一度にディスクに同期しません。InnoDBは、ダーティページを格納するためのリンクリストを作成します。Lruリンクリストで変更されたすべてのページは、このリンクリストのページであるため、このリンクリストに追加する必要があります。すべてディスクにフラッシュする必要があるため、このリンクリストはフラッシュリンクリストとも呼ばれ、リンクリストの構造は無料リンクリストと同じです。

ここでのダーティページの変更とは、このページがバッファプールにロードされた後、初めて変更されることを意味します。初めて変更された場合にのみ、フラッシュリンクリストに追加する必要があります。すでに存在するページの場合フラッシュリンクリストで、このページを再度変更すると、フラッシュリストに配置されなくなります。

ダーティページデータは実際にはまだLruリンクリストにあり、フラッシュリンクリストのダーティページレコードは、ポインタを介してLruリンクリストのダーティページのみを指していることに注意してください。また、フラッシュリンクリスト内のダーティページは、oldest_lsnに従ってソートされ、ディスクにフラッシュされます(この値は、ページが最初に変更されたときのlsn番号を表し、値oldest_modification、各ページヘッダーレコードに対応します)。値が小さいほど、 moreデータの不整合を避けるために、最初に更新されます。

やっと

それはcppです:インタビュアー、これを最初に言わせてください!

インタビュアー:わかりました、答えは悪くありません。(内部OS:この子供はよく知っています!)

それはcppです:私はあなたに感謝することができます!よろしければ、以下をクリックして詳細をご覧ください〜学習の驚きがありますO

 

おすすめ

転載: blog.csdn.net/Python6886/article/details/112471876