MySQL OOM (メモリオーバーフロー) の解決策

MySQL OOM (メモリオーバーフロー) の解決策

OOM は「Out Of Memory」の略で、メモリオーバーフローを意味します。

メモリ オーバーフローは、ソフトウェア開発において 40 年近くにわたって長年問題となってきました。オペレーティングシステム上でさまざまなソフトウェアを実行すると、ソフトウェアが必要とするメモリが物理メモリが保持できるサイズをはるかに超えてしまいます。これをメモリオーバーフローと呼びます。

メモリ オーバーフローにはさまざまな原因があります。メモリが著しく不足している場合、カーネルには次の 2 つのオプションがあります。

  1. 直接的なパニック
  2. いくつかのプロセスを終了して、コアを解放します。

ほとんどの場合、OOM の原因となったプロセスは終了し、システムは回復します。通常、メモリの監視アラームを追加します。たとえば、メモリまたはスワップの使用量が 90% を超えると、アラーム通知がトリガーされ、タイムリーな介入が必要になります。

OOM が発生した場合は、dmesg コマンドで確認できます。CentOS7 以降のバージョンでは、タイムスタンプを時間形式に変換できる -T オプションがサポートされており、特定の時間を簡単に表示できます。

[root@localhost ~]# free -m 使用済み空き共有バッファの合計 cachedMem: 128937 128527 409 1 166 1279-/+ buffers/cache: 127081 1855Swap: 16383 16252 131

ログには、実行中のプロセスや占有しているメモリの量などの情報が表示され、大量のメモリを占有しているプロセスは強制終了されます。

メモリの問題のトラブルシューティング

1. オペレーティングシステムのメモリチェック

MySQL を例にとると、OOM 後、mysqld プロセスが強制終了され、メモリが解放されます。 mysqld_safe プロセスは mysqld を起動し、この時点で表示されるシステム メモリは正常な値になります。メモリ使用量は高いが OOM が発生していない場合、システム メモリ使用量は次のようになります。

[root@localhost ~]# free -m 使用済み空き共有バッファの合計 cachedMem: 128937 128527 409 1 166 1279-/+ buffers/cache: 127081 1855Swap: 16383 16252 131

この時点ですでにメモリ使用量が非常に高いことがわかります。物理メモリとスワップ仮想メモリはほぼ使い果たされています。バッファとキャッシュは多くありません。いつでも OOM が発生する可能性があります。

まず、top を使用して、最も多くのメモリを消費するプロセスを表示します。

shift+o でソート方法を選択でき、n は %MEM を表します。

[root@localhost ~]# topMem: 合計 132031556k、使用済み 131418864k、空き 612692k、バッファー 212104k スワップ: 合計 16777212k、使用済み 0k、空き 16777212k、キャッシュ済み 14648144k
 PID ユーザー PR NI 仮想リソース SHR S %CPU %MEM 時間+ コマンド14920 mysql 20 0 125g 109g 6164 S 6.6 87.0 27357:08 mysqld 

mysqld プロセスが最大のメモリを占有していることがわかります。これは次のように確認することもできます。

130738976 2017 mysql 50032070 mysqld_safe /bin/sh /export/servers/mys 0.0 296 106308 2017 ルート 0

RSZ は、プロセスによって占有されるプライベート メモリのサイズ (KB 単位) です。
VSZ はマップされた仮想メモリのサイズ (KB 単位) です。

合計メモリ使用率は、RSZ/合計で計算することもできます。

2. mysqlに割り当てられたメモリを確認する

MySQL 内のメインメモリは、次のステートメントで確認できます。

MYSQL >SET @giga_bytes = 1024*1024*1024;SELECT (@@key_buffer_size + @@query_cache_size + @@tmp_table_size + @@innodb_buffer_pool_size + @@innodb_additional_mem_pool_size + @@innodb_log_buffer_size + (select count(HOST) from information_schema.processlist)/*@@max_connections*/*(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@binlog_cache_size + @@thread_stack)) / @giga_bytes AS MAX_MEMORY_GB;

各パラメータはサイズを設定します。

***********************************************@@ key_buffer_size:67108864 @@ query_cache_size:0 _pool_size:134217728 @@ innodb_log_buffer_size:8388608 @@ max_connections:3000 @@ read_buffer_size:4194304 binlog_cache_size:32768 @@ thread_stack:262144

各パラメータの設定の説明:

innodb_バッファプールサイズ最も多くのメモリを消費するパラメータ
innodb_追加メモリプールサイズ追加メモリ、MySQL 5.7 以降は削除されました
innodb_log_buffer_size REDOログキャッシュサイズ
キーバッファサイズMyISAM エンジンにのみ使用されるため、大きすぎる必要はありません。
tmp_テーブルサイズ一時テーブルキャッシュサイズ
クエリキャッシュサイズクエリキャッシュは閉じることをお勧めします
最大接続数最大接続数
読み取りバッファサイズ、読み取りrndバッファサイズ、ソートバッファサイズ、結合バッファサイズ、binlogキャッシュサイズ、スレッドスタックこれらのパラメータはすべてスレッドに関連しており、占有されるメモリはこれらのパラメータの合計 * 最大接続数になります。接続数が増えると、占有されるメモリも多くなります。512K を超えないようにすることをお勧めします。binlog_cache_size のデフォルト値は 32K、thread_stack のデフォルト値は 256K です。

MySQL に割り当てる必要があるメモリの量は、上記のパラメータに直接関係します。大きすぎるとメモリ不足につながり、小さすぎるとパフォーマンスに影響します。適切な値をどのように割り当てるかは、ビジネスの状況によって異なります。しかし、ビジネスシナリオは多岐にわたり、ビジネス構成もそれぞれ異なるため、運用・保守コストが高くなります。したがって、ほとんどのシナリオに適した構成テンプレートのセットをカスタマイズするだけで十分です。

1. MySQLによって割り当てられたメモリがシステムメモリより大きい場合

たとえば、システムメモリが 128G の場合、MySQL に割り当てられるメモリはすでに 128G を超えていますが、システム自体や他のプログラムにもメモリが必要であり、mysqldump にもメモリが必要なので、システムメモリが不足し、OOM が発生しやすくなります。このとき、どのパラメータが大きすぎる値に設定されているかを調べ、メモリ割り当てを適切に削減する必要があります。

innodb_buffer_pool は MySQL で最大のメモリを占有します。innodb_buffer_pool_size を減らすと、OOM の問題を効果的に減らすことができます。ただし、値を小さくしすぎると、メモリ内のダーティ ページのフラッシュ頻度が増加し、IO が増加し、パフォーマンスが低下します。通常、innodb_buffer_pool_size はシステム メモリの 60% ~ 75% が最適であると考えられます。

buffer_pool の使用状況を確認します。

mysql> pool_id、pool_size、free_buffers、database_pages、old_database_pages、modified_database_pages、pages_made_young、pages_not_made_young from pages_made_not_made_young -------------------------------+| -----------------------------------+ 309816 ||

buffer_pool が 3 つのインスタンスに分かれていることがわかります。POOL_SIZE は各インスタンスのサイズで、ここではページ数です。MySQL ページのデフォルト サイズは 16K であることがわかっているので、1 つのインスタンスの実際のサイズは 611669*16K です。5.6 以降では、FREE_BUFFERS は少なくとも 1024 ページを保持する必要があります。1024 ページ未満の場合、ダーティ データは強制的にフラッシュされます。次の値は、ダーティ ページの状況を示します。さらに、PAGES_MADE_YOUNG が PAGES_NOT_MADE_YOUNG より大幅に大きい場合、メモリ使用量が比較的大きくなる可能性があり、innodb_buffer_pool_size を適切に削減できます。

別の記事でも buffer_pool が紹介されています: InnoDB ストレージ エンジンを解釈する 1 つのコマンド - show engine innodb status

innodb_buffer_pool_size がそれほど大きくないのにメモリ使用量が非常に高い場合は、同時スレッドが多すぎることが原因である可能性があります。これがアプリケーションの異常なのか、max_connections を調整する必要があるのか​​確認する必要があります。接続が多すぎると、各接続が独立したメモリを占有します。読み取り、並べ替え、結合のキャッシュはすべてセッション レベルにあります。接続が増えるほど、必要なメモリも増えるため、これらのパラメータをあまり大きく設定することはできません。

一部のパラメータは動的な変更をサポートしていないことに注意してください。これらのパラメータは、設定ファイルを変更して MySQL を再起動することによってのみ有効になります。したがって、MySQL を起動する前に、必ずパラメータ値を確認してください。

2. MySQLによって割り当てられたメモリがシステムメモリより小さい場合

MySQL パラメータ設定が適切であるにもかかわらず、OOM が引き続き発生する場合は、システム レベルで MySQL に必要なメモリが不足している可能性があります。MySQL がテーブルを読み取るときに、複数のセッションが同時にテーブルを参照すると、複数のテーブル オブジェクトが作成されるためです。これにより、内部テーブル ロックの競合は軽減されますが、メモリ使用量は増加します。

まず、lsof -p pid を使用して、プロセスによって開かれたシステム ファイルの数を表示します。ここで、pid は mysqld のプロセス ID です。

[root@localhost〜] #ps -ef |。 64/libm-2.12.somysqld 30012 mysql mem reg 8,1 91096 272089/lib64/libz.so.1.2.3mysqld 30012 Mysql Mem Reg 1 43392 272095 /lib64/libcrypt-2.12.somysqld 30012 mysql 10uw reg 8,3 536870912データB_LOGFILE1MYSQLD 30012 MYSQL 12UW REG 8,3 536870912 MYSQL/DATA/IB_LOGFILE2MYSQLD 30012 MYSQL 13UW REG 8,3 675282944 L 14UW REG 8,3 2155872256 58985613 /Mysql/ta/test/table487.ibdmysqld 30012 mysql 15U reg 8,3 0 58982414/mysql/tmp/ibhndzpm 983861 /mysql/data/test/table327.ibdmysqld 30012 mysql 17uw reg 8,3 4169138176 58985467 /mysql Test/table_v199_20170920.ibdmysqld 30012 mysql 19uw reg 8,3 67108864 59015043 /mysql/data/test/table_v39_20170920.ibdmysqld 30012 Mysql 20uw reg 8,37997772790172790172727272 QL/DATA/TEST/TABLE_20170920.IBDMYSQLD 30012 MYSQL 21UW REG 8,3 83886080 59019735 /MYSQL/DATA/TEST/TABLE_V167_20170920.ibdmysQLD 4 /mysql/data/popfin6/table_uuid6.ibdmysqld 30012 mysql 23uw reg 8,3 1275068416 58984491 /mysql/data/test/table_uuid7.ibd..:grot@ w grep〜

MySQL サービスのオープンファイル数の制限を表示します。

MySQL > 'open_files_limit' のようなグローバル変数を表示します。+------------------+-------+| Variable_name | Value |+------------------+-------+| open_files_limit | 65535 |+------------------+-------+

オペレーティング システムのオープン ファイル制限を確認します。

[root@localhost ~]# ulimit -amax メモリサイズ (kbytes, -m) 無制限オープンファイル数 (-n) 65535

この時点で開いているファイルが多いと、大量のメモリが占​​有されます。

次に、table_open_cache を確認する必要があります。テーブルが開かれると、テーブルのファイル記述子がキャッシュされます。

MYSQL >show global variables like 'table_open_cache';+------------------+-------+| Variable_name | Value |+------------------+-------+| table_open_cache | 16384 |+------------------+--------+MYSQL >show global status like '%open%tables%';+-------------------------+--------+| Variable_name | Value |+-------------------------+--------+| Open_tables | 16384 || Opened_tables | 401374 |+-------------------------+--------+

上記の 2 つの値は、table_open_cache がボトルネックに達したかどうかを判断するために使用されます。
キャッシュ内の open_tables の値が table_open_cache の値に近い場合、テーブル キャッシュ プールはほぼいっぱいですが、Opened_tables はまだ増加しており、キャッシュされていないテーブルがまだ多数あることを意味します。

show open tables from schema コマンドを使用して、table_open_cache 内のキャッシュされたテーブルを表示します。繰り返し開かれるテーブルは 1 つだけ表示されます。

MYSQL > sysbenchtest から開いているテーブルを表示します。+--------------+----------+--------+-------------+| データベース | テーブル | 使用中 | 名前がロックされています |+--------------+----------+----------+--------------+| sysbenchtest | sbtest1 | 1 | 0 || sysbenchtest | sbtest2 | 0 | 0 || sysbenchtest | sbtest3 | 0 | 0 || sysbenchtest | sbtest4 | 0 | 0 || sysbenchtest | sbtest5 | 0 | 0 |

In_use は、現在このテーブルを使用しているスレッドの数を示します。 0 より大きい場合は、このテーブルがロックされていることも意味します。

Name_locked は DROP と RENAME にのみ適用されます。DROP または RENAME を実行すると、table_open_cache 内のテーブル ファイル記述子が削除されるため、0 以外の値は表示されません。

一般的に、ライブラリやテーブルの数が多い場合(分割されたライブラリやテーブルの場合)、メモリ使用量が大きくなりやすくなります。根本的な原因を解決したい場合は、ライブラリ テーブルを分割する必要があります。

3. MYSQLのその他のメモリ

information_schema の下にあるすべてのテーブルは MEMORY ストレージ エンジンを使用します。データはメモリ内にのみ保持され、起動時にロードされ、シャットダウン後に解放されます。

システム ライブラリ以外の MEMORY エンジン テーブルがあるかどうかを確認します。

MySQL > select * from information_schema.tables where engine='MEMORY' and TABLE_SCHEMA !='information_schema';

業務で MEMORY ストレージ エンジンを使用している場合は、innodb エンジンに変更してみてください。

4. MYSQLイベントメモリインジケーター

MySQL 5.7 以降では、メモリ割り当ては performance_schema に記録されます。

どのメトリックでメモリ収集が有効になっているかを確認します。

MySQL > select * from performance_schema.setup_instruments where NAME LIKE 'memory/%';

メモリ メトリックの収集を開始します。

MySQL >UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';

インジケーターのメモリ収集結果は、sys ライブラリの下のビューにまとめられます。

MySQL root@[sys]>show tables like 'memory%';+-----------------------------------+| Tables_in_sys (memory%) |+-----------------------------------+| memory_by_host_by_current_bytes || memory_by_thread_by_current_bytes || memory_by_user_by_current_bytes || memory_global_by_current_bytes || memory_global_total |+-----------------------------------+

これらのビューは、デフォルトで降順でイベント タイプ別にグループ化されたメモリ使用量を要約します。

mysql> event_count、current_alloc、sys.memory_global_by_curned> 0; ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 1 MIB || /events_history | 10.49 mib |

要約:

上記の調査により、どの領域がより多くのメモリを占有しているかを大まかに把握し、より多くのメモリを占有している領域に対して具体的な最適化を行うことができます。記事の冒頭で述べたように、メモリオーバーフローはソフトウェア開発の歴史の中で40年近く「長年の」問題となっています。さらに、データベース環境はより複雑です。SQL構文、データ型、データサイズなどの要素はすべてメモリに関連しているため、設計と使用においてメモリオーバーフローの問題をよりよく考慮する必要があります。

以上がMySQL OOM(メモリオーバーフロー)の解決方法の詳細内容です。MySQL OOM(メモリオーバーフロー)の解決方法の詳細については、123WORDPRESS.COMの他の関連記事もご覧ください。

以下もご興味があるかもしれません:
  • MySQL InnoDB ストレージエンジンのメモリ管理の詳細な説明
  • MySQL 8.0 のメモリ消費の詳細な分析
  • MySQL メモリテーブルと一時テーブルの使用方法の詳細な説明
  • MySQLのメモリ使用量を表示する方法の詳細な説明
  • MySQLの一般的なメモリ不足による起動失敗に対する完璧な解決策
  • MySQL のメモリ使用量と CPU 使用率が高い場合のテストと解決策
  • MySQL 5.6 の起動時にメモリ使用量が高くなる問題の解決方法
  • MySQL本番データベースの異常なメモリ増加のトラブルシューティングのプロセスを共有する

<<:  Vue.jsのレンダリング関数の使い方の詳しい説明

>>:  Dockerがプライベート倉庫Harborを構築する手順

推薦する

Linux における「!」の知られざる使用法のまとめ

序文実際、Linux では、控えめな「!」が驚くほど多くの用途で使用されています。この記事では、「!...

HTML メタタグの小さなコレクション

<Head>……</head> は <HTML> のファイル ヘ...

MySQL データベース接続例外の概要 (収集する価値あり)

Centos にプロジェクトをデプロイするときに奇妙な問題が見つかりました。データベース接続で例外...

時間に基づいて日付をクエリするためのMySQL最適化テクニック

たとえば、昨日新規登録されたユーザーを照会するには、次の 2 つの書き方があります。 説明する ch...

MySQL で中国語を入力するときに発生するエラー 1366 の解決方法

MySQL で中国語を入力すると、次のエラーが発生します。エラー 1366: 1366: 行 1 の...

MySQLの左結合を内部結合に素早く変換するプロセス

日々の最適化プロセス中に、奇妙なことに気付きました。同じ SQL にまったく異なる 2 つの実行プラ...

Linux の操作とメンテナンスの基本 httpd 静的 Web ページ チュートリアル

目次1. ウェアハウスを使用してhttpd lrzsz解凍ファイルを作成する2. ソースコードファイ...

JavaScriptにおけるPromiseの使い方と注意点について(推奨)

1. 約束の説明Promise は、非同期操作の最終状態 (失敗または正常完了) とその結果の値を...

Mysql systemctl start mysqld によって報告されるエラーの解決策

エラーメッセージ:制御プロセスがエラー コードで終了したため、mysqld.service のジョブ...

Windows 10 システムで nginx ファイル サーバーを構成するためのグラフィック チュートリアル

Nginx の公式 Web サイトから Windows バージョンの Nginx をダウンロードしま...

JavaScript データ プロキシとイベントの詳細な分析

目次データブローカーとイベントObject.defineProperty メソッドのレビューデータブ...

Vue2 キューブUI 時間セレクターの詳細な説明

目次序文1. 需要と効果必要効果2. コードの実装index.vue(html)日付方法テスト結果3...

Linux seqコマンドの使い方

1. コマンドの紹介seq (シーケンス) コマンドは、指定されたステップ サイズに従って、開始番号...

Vueはシンプルなショッピングカートの例を実装します

この記事では、参考までに、Vue の具体的なコードを共有して、簡単なショッピングカートを実装します。...

MySQL の結合クエリとサブクエリの問題

目次複数テーブル結合の基本構文クロス結合と直積現象クロスコネクトデカルト積現象内部結合外部結合左外部...