このページでは、Cloud SQL インスタンスのメモリ使用量を構成する方法について説明します。
はじめに
Cloud SQL インスタンスを作成する際にインスタンスのメモリ容量を選択します。PostgreSQL データベースのワークロードが増加すると、インスタンスのメモリ使用量も増加します。大量のメモリを消費するインスタンスでは、メモリ不足の問題につながる可能性があるパフォーマンスのボトルネックが発生することがあります。
Cloud SQL インスタンスが需要の増加によりメモリ不足になると、データベースのダウンタイムが発生する可能性があります。したがって、インスタンスのメモリとメモリ関連のデータベース フラグを適切に構成し、メモリ使用量をモニタリングして、インスタンスが正常な状態で動作するようにすることが重要です。
PostgreSQL のメモリ コンポーネントは、大きく次の 2 つの部分に分かれています。
- グローバル メモリ。クエリを実行するすべてのプロセスで共有されます(例:
shared_buffers
、max_connections
など)。 - ローカルメモリ。各接続に割り当てられた専用メモリです(例:
work_mem
、maintenance_work_mem
、temp_buffers
など)。
構成に関するその他の考慮事項については、一般的なベスト プラクティスとオペレーション ガイドラインをご覧ください。
メモリ使用量とフラグ
Cloud SQL インスタンスによるメモリ使用量が多い場合、次のような疑問が生じるかもしれません。
- どのクエリやプロセスがメモリを多く使用しているのか?
- メモリの設定は、データベースの動作に適しているか?
- どのようにすれば、メモリ設定を変更できるか?
PostgreSQL データベースが動作する際に使用されるメモリは、ほとんどが以下のいくつかの領域です。
共有バッファ:
read
とwrite
のオペレーションでテーブルデータを保持するために PostgreSQL が割り当てる共有メモリです。read
オペレーションでは、ディスクからリクエストされたデータはまず RAM に取り込まれ、それからクライアントに渡されます。同様に、PostgreSQL では、データがリクエストされると(SELECT * from emp
など)、まずディスクからshared_buffers
に取り込まれてキャッシュ保存され、続いてクライアントに渡されます。write
オペレーションでも同じことが起こります。共有バッファは、データ キャッシュ保存、接続キャッシュ保存、データ操作言語(DML)オペレーションなどのデータベース アクティビティのすべてのプロセスと接続の共有メモリ領域でもあります。この領域に割り当てることができる最大値は
shared_buffers
フラグで指定され、デフォルトはインスタンスのメモリの 33% です。shared_buffers
の値が大きい場合、メモリにキャッシュ保存されているデータのサイズは大きくなります。- クエリの作業メモリ: PostgreSQL は、クエリの実行時に、並べ替えやハッシュなどのオペレーションごとにローカルメモリを割り当てます。一時ディスク ファイルに書き込む前にクエリの各オペレーションに割り当てることができる最大値は、
work_mem
フラグによって構成され、デフォルト値は 4 MB です。work_mem
の値が大きければ、メモリ内で並べ替え可能なデータの量が多くなります。 - メンテナンス用の作業メモリ:
VACUUM
、CREATE INDEX
、ALTER TABLE
、ADD FOREIGN KEY
などの一部のメンテナンス オペレーションでは、PostgreSQL が割り当てる個別のローカルメモリが必要になります。これらのオペレーションで使用するバックエンド プロセスの最大量はmaintenance_work_mem
フラグで構成できます。デフォルト値は 64 MB です。なお、自動バキューム ワーカーもメンテナンス用の作業メモリを使用し、その最大値がautovacuum_work_mem
フラグでオーバーライドできることに注意してください。maintenance_work_mem
の値が大きければ、VACUUM
オペレーションの実行速度は速くなります。 - 一時バッファ: データベース セッションで一時テーブルが使用されると、PostgreSQL はセッション ローカルの一時テーブルを保持するために一時バッファを割り当てます。最大量は
temp_buffers
フラグで指定でき、デフォルト値は 8 MB です。 - データベース接続: クライアントがデータベースに接続すると、PostgreSQL はクライアント セッションを提供するバックエンド プロセスを作成します。クエリを実行するためのメモリに加えて、PostgreSQL はシステム カタログ キャッシュや準備されたクエリプランなどの情報を保持するために追加のメモリを割り当てます。データベース サーバーに対して許可される同時接続の最大数は、
max_connections
フラグで構成できます。各アイドル状態の接続では、約 2 MB~3 MB の共有メモリが使用されます。max_connections
の値が大きい場合、インスタンスにはさらに多くの接続が可能になりますが、メモリの使用量は増えます。
PostgreSQL におけるメモリ コンポーネントの完全なリストについては、PostgreSQL のドキュメントをご覧ください。このセクションに記載されているフラグを変更または修正するには、データベース フラグを構成するをご覧ください。
メモリ使用量をモニタリングする
Cloud Monitoring で定期的にインスタンスのメモリをモニタリングし、メモリの上限を超えないようにします。Cloud Monitoring でアラートを設定し、使用量が 6 時間の上限の 90% を超えた場合にアラートを送信することをおすすめします。このアラートにより、メモリ使用量が上限に近づくと必ず警告を出せます。
さらに、メモリ不足インシデントをモニタリングします。そのために、Cloud Monitoring で server process .* was terminated by signal 9: Killed
メッセージのログベースの指標を設定してメモリ不足イベントをカウントし、そのようなイベントが発生するたびにアラートを出します。
インスタンスが常にメモリの上限の 90% 以上で動作している場合、またはメモリ不足イベントが発生した場合は、インスタンスのメモリを増やすことができます。あるいは、データベース接続の数を制限するか、shared_buffers
、work_mem
、max_connections
などのデータベース フラグを低くして、メモリ使用量を減らすこともできます。これらのフラグを低くすると、インスタンスのパフォーマンスが制限される可能性があります。
メモリ不足
データベースのワークロードを処理するのに十分なメモリがない場合、最後の手段として、基盤となる Linux オペレーティング システムは out-of-memory (OOM) killer
を使用してプロセスを終了し、メモリを解放します。Cloud SQL は、OOM killer
が PostgreSQL ワーカー プロセスのみをターゲットとするように構成されています。ポストマスター プロセスはこの状況で保持されるため、既存のデータベース接続をすべて終了して、データベースの完全性を保つために復元を実行するだけでよいのです。このような事態が発生すると、データベースでサービスが停止し、ダウンタイムが発生します。PostgreSQL データベース ログには、以下のようなメッセージが表示されます。
2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed 2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col 2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes 2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process 2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. 2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command. 2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab" ... 2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode ... 2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing ... 2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC 2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress 2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400 2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508 2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00 2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections
次のステップ
- PostgreSQL のメモリ使用量の構成について詳細を確認する。
- PostgreSQL サーバーをチューニングする。