目次
バッファ プール
バッファ プールの構成
フリーリンクリスト
キャッシュされたページのハッシュ処理
フラッシュ リンク リストの管理
刷新脏页
多个buffer pool实例
动态调整buffer pool大小
查看buffer pool具体的信息
ホームページ データベース mysql チュートリアル MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

Jun 03, 2023 am 10:40 AM
mysql buffer pool

バッファ プール

ページを読み取るときは、最初にページをディスクからメモリに読み取り、次に CPU がデータを処理するのを待つ必要があることは誰もが知っています。ディスクからメモリにデータを読み取るプロセスは非常に遅いため、読み取ったページをキャッシュする必要があるため、MySQL にはページをキャッシュするためのバッファ プールがあります。

まず、MySQL は起動時にオペレーティング システムから連続メモリ領域を申請し、この領域をバッファ プールとして使用します。キャッシュされたページをバッファプールに入れて管理します。

mysql> show variables like 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
1 row in set, 1 warning (0.00 sec)
ログイン後にコピー

デフォルトは 134217728 バイト、つまり 128MB であることがわかります。申請するキャッシュ サイズが 16 KB の倍数である場合、各ページ サイズは 16 KB であるため、断片化の問題は発生しません。

バッファ プールの構成

各ページには、バッファ プールに格納される、対応する制御ブロック情報が含まれています。各制御ブロックは各ページを管理します (各ページを参照するためにアドレスを使用します)。制御ブロックはページに関する情報を保存するために使用されます。制御ブロックの占有サイズは innodb_buffer_pool_size には含まれません。 MySQL は起動時に追加のスペースを適用します。

MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

スペースを完全に利用できないため、制御ブロックとキャッシュ ページの間に不規則な断片化が発生します。 MySQL がオペレーティング システムに適用するメモリ領域には、一定サイズの制御ブロック領域が必要ですが、具体的なサイズは決定できないため、使用できない領域が生じることは避けられません。

フリーリンクリスト

フリーリンクリストはその名の通り、フリーキャッシュページを管理するリンクリストで、キャッシュページを使用しない場合はそのコントロールブロックが接続されます。無料のリンクリスト。

MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

#コントロール ブロックをベース ノードを介して接続してフリー リンク リストを形成し、フリー ページ数などの基本情報を保存します。

ディスクからバッファ プールにページを読み取るとき、空き制御ブロックを取得し、対応するキャッシュ ページの基本情報を書き込みます。

キャッシュされたページのハッシュ処理

MySQL はどのようにしてバッファ プール内のページに素早くアクセスし、対応するページがバッファ プールにキャッシュされているかどうかを確認するのでしょうか?

これは、Java のハッシュマップであるハッシュ テーブルを使用しています。テーブル スペースのページ番号が処理されてハッシュ キー値が形成され、その値がバッファ プール内のキャッシュ ページのアドレスになります。 。

フラッシュ リンク リストの管理

この章を知ったときは、まず自分の理解とかなり違っていて、その後の MVCC で本当に衝撃を受けました。 eye-opener. 一度勉強してからまとめたものなので、比較的簡潔にまとまっています。

SQL ステートメントを使用して特定のレコードを変更する場合、特定のページまたは複数のページを変更します。ページを変更する場合、対応する変更をディスクに直接行うことはありません。 IO が遅すぎるため、最初に変更されたページ (略してダーティ ページ) をリンクします。これはフリー リンク リストに似ています。つまり、ベース ノードがダーティ ページに対応する制御ブロックをまとめて接続します。

このフラッシュ リンク リストは、まだページをディスクに更新していないリンク リストを表します。

MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

#LRU リンク リスト

バッファ プールのサイズが制限されているため、キャッシュ ページのサイズも制限されているため、未使用のページを分離する必要があります消去法を実行します。 MySQL は、削除に LRU メソッドを使用します。

LRU は、最長未使用の削除戦略です。キャッシュされたページをリンクするには、リンク リストを使用します。最近アクセスされたページが先頭に表示され、最もアクセスの少ないページがリンク リストの最後に表示されます。 LRU がいっぱいです。新しいページが挿入されます。リンクされたリストの末尾のページを削除します。

LRU を直接使用します。MySQL が事前読み取りまたはテーブル全体のスキャンを実行すると、大量の低頻度ページが LRU リンク リストに読み込まれます。これにより、高頻度ページが直接削除され、使用頻度の低いページに置き換えられます。

MySQL オプティマイザは、クエリによってアクセスされることが予想されるページをメモリ バッファ プールにプリロードして、クエリのパフォーマンスを向上させます。

  • 線形先読み

領域内のページの読み取りがシステム変数 innodb_read_ahead_threshold の値を超える場合、デフォルトは 56 です。つまり、ある領域で 56 ページを超えるページを読み取ると、MySQL は次の領域のすべてのページをメモリに非同期的に読み取ります。

  • ランダム先読み

バッファ プールがシーケンシャルであるかどうかに関係なく、特定の領域に 13 ページをキャッシュした場合、ページがキャッシュされると、MySQL がトリガーされ、この領域内のすべてのページが MySQL に非同期的に読み込まれます。システム変数 innodb_random_read_ahead を設定すると、ランダムな先読みをオフにすることができます。デフォルトはオフです。

そのため、リンク リストを 2 つの部分に分割する、改良されたパーティション ベースの LRU リンク リストが存在します。

1 つは非常に頻繁に使用される若い領域、もう 1 つはあまり使用されない古い領域です。

正常来说old区占比是37%,所以young区就占63%,我们可以通过innodb_old_blocks_pct来修改,默认就是37。

我们来讲讲这个基于分区的LRU链表。

  1. 首先buffer pool初始化,会将读取的页面直接放进old区。

  • 但是如果我们对于同一个页面的多条记录进行访问的话,我们就会多次访问同一页多次。但是如果我们是全表扫描的话,是可能会将所有页面缓存进缓存池中的,所以MySQL对于其进行优化。

  • 所以MySQL对于当页面第一次读入old区并在一定时间间隔(innodb_old_blocks_pct)内的多次访问来说是不会将其放入young区进行缓存的。innodb_old_blocks_pct的值默认为1000,就是刚来的来一秒内的多次访问是不会将其转移到young区的。

  1. 如果多次访问就会将old区的页升级到young区。当young区的页面被访问,只有young链表后1/4的页面被访问时才会将其转置到young区链表头,不然就不会改动,减少一些调整链表的性能损失。

刷新脏页

MySQL会启动后台线程进行脏页,也就是修改的页面进行刷新到磁盘。

以下有两种方式刷新脏页:

  • 从LRU的尾部扫描一些页面,刷新其中的脏页到磁盘中。

    • 在LRU链表的old区域尾部,即不经常使用的页面中,后台线程会查找是否存在脏页,如果有,则将其更新至磁盘。控制扫描区域尾部数量的方法是更改系统变量innodb_lru_scan_depth。

  • 从flush链表中更新到磁盘。

    • 我们上面说了flush连接这脏页的控制块,我们就可以将连接这flush链表的脏页进行更新。

疑问:为什么要两种方式更新呢?我刚开始不懂这是我回过头来看的时候就懂了

首先我们脏页是缓存在buffer pool中的,但是我们buffer pool空间是有限的,又因为我们使用的是LRU的方式,又因为从flush链表将脏页同步到磁盘效率实在不高,所以不会很经常去更新脏页。如果我们不更新直接将其从LRU的链表抛弃也就是从缓存池中直接扔了,但是它是脏页就无法同步到磁盘了,同时flush链表链接的也会出现问题。

所以在LRU淘汰很久未使用的页有个前提就是它不是一个脏页。为了淘汰这些页面,我们需要检查LRU链表的末尾是否存在脏页并进行更新。

flush链表更新那就是它的本职工作了,它存这个也是干这个的,应该没有什么问题。

当系统十分繁忙,buffer pool使用量不足的时候,因为磁盘IO太慢了,所以会出现一种情况,就是大量的用户线程也在进行这个同步脏页的活。如果未进行脏页同步并淘汰缓冲池的页面,则无法读取该页面。

多个buffer pool实例

我们可以设置多个buffer pool来实现多实例提高性能。

mysql> show variables like 'innodb_buffer_pool_instances';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| innodb_buffer_pool_instances | 1     |
+------------------------------+-------+
1 row in set, 1 warning (0.00 sec)
ログイン後にコピー

我们可以设置innodb_buffer_pool_instances系统变量来控制实例变量。

但是当buffer pool的大小小于1G的时候,设置2个实例也是没有用的(会被恢复成1个),多实例的情况是建立在大内存的情况下的。

动态调整buffer pool大小

在MySQL5.7.5后,MySQL中的buffer pool的大小是以chunk来分配了,如下图。

MySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?

一个buffer pool是由多个chunk组成的,所以MySQL向操作系统申请连续的内存空间,就是以chunk的方式来申请的,这样我们可以在MySQL运行时调整buffer pool的大小。在运行时更改chunk大小不可行,并且会造成性能浪费。?

innodb_buffer_pool_size / innodb_buffer_pool_instances = 每个实例buffer pool的大小。

每个实例的大小 / innodb_buffer_pool_chunk_size = 每个实例由多少个chunk构成。

不是弄很明白,怎么动态调整大小,我调整了但是mysqld占用内存大小还是只能重启才能生效,我不会。

查看buffer pool具体的信息

show engine innodb status;
ログイン後にコピー

以上がMySQL でのページ バッファ プールの読み取りに関する知識ポイントは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPのビッグデータ構造処理スキル PHPのビッグデータ構造処理スキル May 08, 2024 am 10:24 AM

PHPのビッグデータ構造処理スキル

PHP で MySQL クエリのパフォーマンスを最適化するにはどうすればよいですか? PHP で MySQL クエリのパフォーマンスを最適化するにはどうすればよいですか? Jun 03, 2024 pm 08:11 PM

PHP で MySQL クエリのパフォーマンスを最適化するにはどうすればよいですか?

PHP で MySQL のバックアップと復元を使用するにはどうすればよいですか? PHP で MySQL のバックアップと復元を使用するにはどうすればよいですか? Jun 03, 2024 pm 12:19 PM

PHP で MySQL のバックアップと復元を使用するにはどうすればよいですか?

PHP を使用して MySQL テーブルにデータを挿入するにはどうすればよいですか? PHP を使用して MySQL テーブルにデータを挿入するにはどうすればよいですか? Jun 02, 2024 pm 02:26 PM

PHP を使用して MySQL テーブルにデータを挿入するにはどうすればよいですか?

データベースにおける Java 列挙型のアプリケーション シナリオは何ですか? データベースにおける Java 列挙型のアプリケーション シナリオは何ですか? May 05, 2024 am 09:06 AM

データベースにおける Java 列挙型のアプリケーション シナリオは何ですか?

MySQL 8.4 で mysql_native_password がロードされていないエラーを修正する方法 MySQL 8.4 で mysql_native_password がロードされていないエラーを修正する方法 Dec 09, 2024 am 11:42 AM

MySQL 8.4 で mysql_native_password がロードされていないエラーを修正する方法

PHP で MySQL ストアド プロシージャを使用するにはどうすればよいですか? PHP で MySQL ストアド プロシージャを使用するにはどうすればよいですか? Jun 02, 2024 pm 02:13 PM

PHP で MySQL ストアド プロシージャを使用するにはどうすればよいですか?

PHP 配列ページングのパフォーマンス最適化戦略 PHP 配列ページングのパフォーマンス最適化戦略 May 02, 2024 am 09:27 AM

PHP 配列ページングのパフォーマンス最適化戦略

See all articles