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を構築する手順

推薦する

MySQL の FIND_IN_SET() と IN の違いを簡単に分析します

以前、あるプロジェクトでMysql FIND_IN_SET関数を使用したことがありますが、非常に便利...

ウェブページのコピー防止機能の実装方法(クラッキング手法付き)

ソース ファイルを右クリックすると、次のコードが見つかります。 1. CSSを使用してFirefox...

Vueプロジェクトの支払い機能コードの詳細な説明

1. Alipay方式: Alipay メソッド: Alipay をクリックして支払い、バックエンド...

Linux で xargs コマンドを使用する詳細なチュートリアル

みなさんこんにちは。私は梁旭です。 Linux を使用しているときに、いくつかのコマンドを連結する必...

MySql 8.0.11 のインストールと設定のチュートリアル

公式ウェブサイトアドレス: https://dev.mysql.com/downloads/mysq...

Markodwnによるタイトル配置による同期スクロールのアイデアの詳細な説明

序文私が作成中の Markodwn エディターに同期スクロール機能を追加する必要があります。Baid...

Mysql5.6.36 スクリプトのコンパイル、インストール、初期化のチュートリアル

概要この記事は、centos7.3 上で mysql5.3.6 を自動的にコンパイルしてインストール...

vsFTP 3.0.3 のコンパイルとインストールの詳細な分析

脆弱性の詳細VSFTP は、GPL に基づいてリリースされた Unix ライクなシステムで使用される...

GaussDB for MySQL パフォーマンス最適化の詳細な説明

目次背景インスピレーションは人生から生まれる速達配送の最適化原則GaussDB の最適化 (MySQ...

vue + Electron でデスクトップ アプリケーションを作成するためのサンプル コード

1.vueパッケージングここでは、vueネイティブパッケージングコマンドを使用してvueプロジェクト...

HTML は Double 11 クーポン取得を実装します (クーポン取得ページを開く時間を設定します)

さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <!DOCTYPE htm...

ウェブデザインと制作に関する科学的原則と提案の要約

<br />ネットワーク設計の分野では、アイトラッキングに関する研究が非常に盛んに行われ...

mysqlのデータディレクトリ内のファイルを直接コピーしてデータを復元する実装

mysqlはデータディレクトリ内のファイルをコピーしてデータを復元します背景: MySQL がクラッ...

静的ページと動的ページの実行メカニズムの説明

1. 静的ページとは、Web ページ内に HTML タグのみが含まれるページです。WEB 開発者がこ...

MySQL 8.0.12 のインストールと設定方法のグラフィックチュートリアル (Windows 版)

1. はじめにプロジェクトではMySQLを使用しています。インターネット上の例を参考にインストール...