パフォーマンスの高いMySQLデータベースサーバーの重要な要素の1つは、特に実稼働環境で実行する場合に、メモリの割り当てと使用率が高いことです。しかし、MySQLの使用率が最適化されているかどうかをどのように判断できますか?メモリ使用率を高くすることは合理的ですか、それとも微調整が必要ですか?メモリリークが発生した場合はどうなりますか?
これらのトピックを取り上げ、MySQLでチェックしてメモリ使用率の高い痕跡を特定できることを示しましょう。
MySQLでのメモリ割り当て
特定のサブジェクトタイトルを掘り下げる前に、MySQLがメモリをどのように使用するかについて簡単に説明します。同時トランザクションを処理し、大きなクエリを実行する場合、メモリは速度と効率のために重要なリソースを果たします。 MySQLの各スレッドは、クライアント接続の管理に使用されるメモリを必要とし、これらのスレッドは同じベースメモリを共有します。 thread_stack(スレッドのスタック)、net_buffer_length(接続バッファーと結果バッファーの場合)、または接続と結果が必要に応じてこの値まで動的に拡大するmax_allowed_packetのような変数は、メモリ使用率に影響を与える変数です。スレッドが不要になると、スレッドがスレッドキャッシュに戻らない限り、スレッドに割り当てられたメモリが解放されてシステムに戻されます。その場合、メモリは割り当てられたままになります。クエリ結合、クエリキャッシュ、並べ替え、テーブルキャッシュ、テーブル定義にはMySQLのメモリが必要ですが、これらは構成および設定できるシステム変数に起因します。
ほとんどの場合、構成に設定されたメモリ固有の変数は、MyISAMやInnoDBなどのストレージベースの特定の構成を対象としています。 mysqldインスタンスがホストシステム内で生成されると、MySQLはバッファーとキャッシュを割り当てて、特定の構成で設定された設定値に基づいてデータベース操作のパフォーマンスを向上させます。たとえば、すべてのDBAがInnoDBに設定する最も一般的な変数は、変数innodb_buffer_pool_sizeとinnodb_buffer_pool_instancesであり、どちらもInnoDBテーブルのキャッシュデータを保持するバッファープールのメモリ割り当てに関連しています。大きなメモリがあり、バッファプールを複数のバッファプールインスタンスに分割して同時実行性を向上させるためにinnodb_buffer_pool_instancesを設定して、大きなトランザクションを処理することを期待している場合は望ましいです。
MyISAMの場合、キーバッファが処理するメモリの量を処理するには、key_buffer_sizeを処理する必要があります。 MyISAMは、テーブル構造を含むすべての同時スレッドにバッファーを割り当て、各列に列構造を割り当て、サイズ3 * Nのバッファーを割り当てます(Nは最大行長であり、BLOB列は含まれません)。 MyISAMは、内部使用のために1つの追加の行バッファーも維持します。
MySQLは、一時テーブルが大きくなりすぎない限り(tmp_table_sizeおよびmax_heap_table_sizeによって決定される)、一時テーブルにもメモリを割り当てます。 MEMORYテーブルを使用していて、変数max_heap_table_sizeが非常に高く設定されている場合、max_heap_table_sizeシステム変数がテーブルのサイズを決定し、オンディスク形式への変換がないため、これも大きなメモリを消費する可能性があります。
MySQLには、MySQLアクティビティを低レベルで監視するための機能であるパフォーマンススキーマもあります。これを有効にすると、サーバーの起動時に必要なメモリを割り当てるのではなく、メモリを段階的に動的に割り当て、メモリ使用量を実際のサーバー負荷に合わせてスケーリングします。メモリが割り当てられると、サーバーが再起動されるまでメモリは解放されません。
Linuxを使用している場合、およびカーネルがラージページのサポートに対して有効になっている場合、つまりHugePagesを使用している場合は、MySQLを構成してバッファプールに大容量のメモリを割り当てることもできます。
MySQL DBAが、実行中のMySQLサーバーで何が起こっているかを最初にベースにタッチすることは非常に一般的です。最も基本的な手順は、プロセスリストの確認、サーバーステータスの確認、およびストレージエンジンのステータスの確認です。これらのことを行うには、基本的に、MySQLにログインして一連のクエリを実行する必要があります。以下を参照してください:
実行中のクエリを表示するには、
mysql> SHOW [FULL] PROCESSLIST;
現在のプロセスリストを表示すると、アクティブに実行されているクエリ、またはアイドル状態またはスリープ状態のプロセスでさえあるクエリが明らかになります。実行中のクエリの記録を保持することは非常に重要であり、重要なルーチンです。 MySQLがメモリを割り当てる方法について説明したように、クエリを実行するとメモリ割り当てが利用され、監視しないとパフォーマンスの問題が大幅に発生する可能性があります。
MySQLサーバーのステータス変数を表示します
mysql> SHOW SERVER STATUS\G
mysql> SHOW SERVER STATUS WHERE variable_name IN ('<var1>', 'var2'...);
MySQLのステータス変数は、統計データとして機能し、メトリックデータを取得して、ステータス値によって指定されたカウンターを監視することにより、MySQLのパフォーマンスを判断します。ここには、メモリ使用率に影響を与える一目でわかる特定の値があります。たとえば、スレッドの数、テーブルキャッシュの数、またはバッファプールの使用状況を確認します。
...
| Created_tmp_disk_tables | 24240 |
| Created_tmp_tables | 334999 |
…
| Innodb_buffer_pool_pages_data | 754 |
| Innodb_buffer_pool_bytes_data | 12353536 |
...
| Innodb_buffer_pool_pages_dirty | 6 |
| Innodb_buffer_pool_bytes_dirty | 98304 |
| Innodb_buffer_pool_pages_flushed | 30383 |
| Innodb_buffer_pool_pages_free | 130289 |
…
| Open_table_definitions | 540 |
| Open_tables | 1024 |
| Opened_table_definitions | 540 |
| Opened_tables | 700887 |
...
| Threads_connected | 5 |
...
| Threads_cached | 2 |
| Threads_connected | 5 |
| Threads_created | 7 |
| Threads_running | 1 |
InnoDBステータスなど、エンジンのモニターステータスを表示します
mysql> SHOW ENGINE INNODB STATUS\G
InnoDBステータスは、ストレージエンジンが処理しているトランザクションの現在のステータスも示します。トランザクションのヒープサイズ、そのバッファ使用量を明らかにするアダプティブハッシュインデックス、または以下の例のようにinnodbバッファプール情報を表示します。
---TRANSACTION 10798819, ACTIVE 0 sec inserting, thread declared inside InnoDB 1201
mysql tables in use 1, locked 1
1 lock struct(s), heap size 1136, 0 row lock(s), undo log entries 8801
MySQL thread id 68481, OS thread handle 139953970235136, query id 681821 localhost root copy to tmp table
ALTER TABLE NewAddressCode2_2 ENGINE=INNODB
…
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 528, free list len 43894, seg size 44423, 1773 merges
merged operations:
insert 63140, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 637 buffer(s)
Hash table size 553193, node heap has 772 buffer(s)
Hash table size 553193, node heap has 1239 buffer(s)
Hash table size 553193, node heap has 2 buffer(s)
Hash table size 553193, node heap has 0 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
115320.41 hash searches/s, 10292.51 non-hash searches/s
...
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2235564032
Dictionary memory allocated 3227698
Internal hash tables (constant factor + variable factor)
Adaptive hash index 78904768 (35404352 + 43500416)
Page hash 277384 (buffer pool 0 only)
Dictionary cache 12078786 (8851088 + 3227698)
File system 1091824 (812272 + 279552)
Lock system 5322504 (5313416 + 9088)
Recovery system 0 (0 + 0)
Buffer pool size 131056
Buffer pool size, bytes 2147221504
Free buffers 8303
Database pages 120100
Old database pages 44172
Modified db pages 108784
Pending reads 0
Pending writes: LRU 2, flush list 342, single page 0
Pages made young 533709, not young 181962
3823.06 youngs/s, 1706.01 non-youngs/s
Pages read 4104, created 236572, written 441223
38.09 reads/s, 339.46 creates/s, 1805.87 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 12 / 1000 not 5 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 120100, unzip_LRU len: 0
I/O sum[754560]:cur[8096], unzip sum[0]:cur[0]
…
もう1つ追加することとして、MySQLサーバーによるメモリ消費と使用率を監視するためにパフォーマンススキーマとsysスキーマを使用することもできます。デフォルトでは、ほとんどのインストルメンテーションはデフォルトで無効になっているため、これを使用するには手動で行う必要があります。
どちらの方法でも、MySQLがメモリをディスクにスワップアウトしている可能性があります。これは、特にMySQLサーバーと基盤となるハードウェアが、予想される要件と並行して最適に設定されていない場合に、非常に一般的な状況になることがよくあります。トラフィックの需要が予測されていない場合があります。特に、不正なクエリが実行されて大量のメモリスペースが消費または使用され、データがバッファではなくディスクで選択されるため、パフォーマンスが低下する場合は、メモリがますます増大する可能性があります。 swappinessを確認するには、以下のようにfreememコマンドまたはvmstatを実行します。
[[email protected] ~]# free -m
total used free shared buff/cache available
Mem: 3790 2754 121 202 915 584
Swap: 1535 39 1496
[[email protected] ~]# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 40232 124100 0 937072 2 3 194 1029 477 313 7 2 91 1 0
0 0 40232 123912 0 937228 0 0 0 49 1247 704 13 3 84 0 0
1 0 40232 124184 0 937212 0 0 0 35 751 478 6 1 93 0 0
0 0 40232 123688 0 937228 0 0 0 15 736 487 5 1 94 0 0
0 0 40232 123912 0 937220 0 0 3 74 1065 729 8 2 89 0 0
procfsを使用して確認し、/ proc/vmstatや/proc/meminfoに移動するなどの情報を収集することもできます。
MassifでのPerf、gdb、Valgrindの使用
perf、gdb、valgrindなどのツールを使用すると、MySQLのメモリ使用率を判断するためのより高度な方法を掘り下げるのに役立ちます。興味深い結果がメモリ消費を解決する謎になり、MySQLに戸惑うことがあります。これにより、より懐疑的な見方が必要になります。これらのツールを使用すると、MySQLがメモリの割り当てからトランザクションまたはプロセスの処理に使用するまで、メモリの処理をどのように使用しているかを調査できます。これは、たとえば、MySQLが異常な動作をしていて、構成が正しくないか、メモリリークが検出される可能性があることを確認している場合に役立ちます。
たとえば、MySQLでperfを使用すると、システムレベルのレポートでより多くの情報が明らかになります。
[[email protected] ~]# perf report --input perf.data --stdio
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 54K of event 'cpu-clock'
# Event count (approx.): 13702000000
#
# Overhead Command Shared Object Symbol
# ........ ....... ................... ...................................................................................................................................................................................................
#
60.66% mysqld [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
2.79% mysqld libc-2.17.so [.] __memcpy_ssse3
2.54% mysqld mysqld [.] ha_key_cmp
1.89% mysqld [vdso] [.] __vdso_clock_gettime
1.05% mysqld mysqld [.] rec_get_offsets_func
1.03% mysqld mysqld [.] row_sel_field_store_in_mysql_format_func
0.92% mysqld mysqld [.] _mi_rec_pack
0.91% mysqld [kernel.kallsyms] [k] finish_task_switch
0.90% mysqld mysqld [.] row_search_mvcc
0.86% mysqld mysqld [.] decimal2bin
0.83% mysqld mysqld [.] _mi_rec_check
….
これは掘り下げる特別なトピックになる可能性があるため、参照としてこれらの非常に優れた外部ブログを調べること、MySQLプロファイリングのperf Basics、perfを使用したMySQLスケーリングの問題の発見、または方法を学ぶことをお勧めしますmassifでvalgrindを使用してデバッグします。
ClusterControlを使用すると、Runbookを調べたり、レポートを配信する独自のプレイブックを作成したりするなどの面倒なルーチンが軽減されます。 ClusterControlには、MySQLノードの概要をすばやく確認できるダッシュボード(SCUMMを使用)があります。たとえば、MySQLGeneralダッシュボードを表示する
MySQLノードのパフォーマンスを判断できます
上の画像は、MySQLのメモリ使用率に影響を与える変数を示しています。ソートキャッシュ、一時テーブル、接続されたスレッド、クエリキャッシュ、またはストレージエンジンのinnodbバッファプールまたはMyISAMのキーバッファのメトリックを確認できます。
ClusterControlを使用すると、実行中のクエリをチェックして、高いメモリ使用率に影響を与える可能性のあるプロセス(クエリ)を特定できるワンストップユーティリティツールが提供されます。例については、以下を参照してください
MySQLのステータス変数の表示は非常に簡単です
[パフォーマンス]->[Innodbステータス]に移動して、データベースノードの現在のInnoDBステータス。また、ClusterControlでは、インシデントが検出され、インシデントの収集を試み、MySQLFreezeFrameに関する以前のブログで示したようにInnoDBステータスを提供するレポートとして履歴を表示します。
使用する手順とツールを知っている限り、メモリ使用率が高いと思われる場合のMySQLデータベースのトラブルシューティングと診断はそれほど難しくありません。適切なツールを使用すると、柔軟性と生産性が向上し、修正やソリューションを提供して、より大きな成果を上げることができます。