やあ、今日もPostgreSQLと格闘してる?
エンジニアとしてデータベースを触っていると、「SQLが遅い」「ロック待ちが発生した」なんて壁に必ずぶつかるよね。そのとき、多くの人はEXPLAINの結果を眺めたり、インデックスを貼ったりする。それは正しい。でも、もう少しだけ「PostgreSQLの脳みそ」を覗いてみると、トラブルシューティングの解像度が劇的に変わるんだ。
今日は、その脳みその心臓部、「共有メモリ(Shared Memory)」について話をしよう。
—
共有メモリは「全員で共有する巨大な机」だ
PostgreSQLは、クライアントごとの接続を「プロセス」として立ち上げるアーキテクチャだよね。でも、もし各プロセスが自分のメモリだけで全ての処理を完結させようとしたらどうなると思う? データの整合性は取れないし、メモリの無駄遣いでサーバーは一瞬でパンクする。
そこで登場するのが「共有メモリ」だ。これは、全プロセスがアクセスできる「巨大な机」のようなもの。ここに全員が使うデータを置いておくことで、効率よく、かつ整合性を保って動いているんだ。
具体的に何が置かれているか、主要な3つだけ覚えて帰ってくれ。
1. 共有バッファ(Shared Buffers): ディスク上のデータ(テーブルやインデックス)をキャッシュする場所。ここが一番の主役だ。
2. WALバッファ(WAL Buffers): データの変更履歴をディスクに書き込む前の一時置き場。
3. ロックテーブル(Lock Table): 今どの行が誰に使われているかを管理する地図。
—
なぜ「共有バッファ」のチューニングが重要なのか
実務で一番気にすべきは、やっぱり「共有バッファ」だ。
ここが小さいと、PostgreSQLは頻繁にディスク(I/O)へ読み込みに行くことになる。現代のサーバーはCPUが速くても、ストレージのI/O待ちが一番のボトルネックになりがちだ。「メモリを積んでいるのにDBが遅い」という時は、ここがデフォルト値(大抵は控えめな設定)のまま放置されていることが多い。
チューニングの目安
`postgresql.conf` の `shared_buffers` を確認してみてほしい。
多くの本番環境では、物理メモリの25%程度を割り当てるのが定石だ。
postgresql.conf
物理メモリが64GBのサーバーなら、16GB程度を目安に設定する
shared_buffers = 16GB
ただし、欲張ってメモリを割り当てすぎると、OS側のファイルシステムキャッシュが圧迫されて逆効果になることもある。この「バランス」こそが、経験の差が出る場所だね。
—
ロックテーブル:地獄の入り口と出口
次に「ロックテーブル」。ここは、同時実行制御の肝だ。
もし、あるセッションが大量の行を更新してロックをかけると、その情報は共有メモリ内のロックテーブルに書き込まれる。他のプロセスは、「おっと、ロックテーブルに名前があるから今は触れないな」と判断して待機するわけだ。
ここで一つ、実務的なアドバイス。
「長すぎるトランザクションは、ロックテーブルを汚す」と覚えておいてくれ。
— こんな書き方は要注意
BEGIN;
UPDATE products SET stock = stock – 1 WHERE id = 1;
— ここで外部APIを叩いたり、重い処理を挟んだりする(最悪!)
— ロックが解放されず、他のプロセスが次々とロック待ちで沈んでいく
COMMIT;
共有メモリ上のロックテーブルには上限がある。あまりに多くのロックを保持し続けると、最悪の場合、メモリ不足やパフォーマンス低下を招く。トランザクションは「短く、鋭く」が鉄則だ。
—
現場で使える「覗き見」テクニック
最後に、今の共有メモリがどうなっているか確認する方法を教えておくよ。`pg_buffercache` という拡張機能を使うんだ。
— 拡張機能を有効化
CREATE EXTENSION pg_buffercache;
— どのテーブルが共有バッファを多く占有しているか確認
SELECT c.relname, count() AS buffers
FROM pg_buffercache b
JOIN pg_class c ON b.relfilenode = pg_relation_filenode(c.oid)
GROUP BY c.relname
ORDER BY buffers DESC
LIMIT 10;
これを使うと、「今、メモリに何が乗っているのか」が丸裸になる。「あれ、このインデックス、全然使われてないのにバッファを食い荒らしているな」なんて発見があると、チューニングのヒントになるはずだ。
—
まとめ
共有メモリは、PostgreSQLが「速く、安全に」動くための血液のようなものだ。
- 共有バッファは、サーバーのI/O性能を左右する。
- ロックテーブルは、同時実行の秩序を守る。
教科書の知識も大事だけど、こうやって「裏側で何が起きているか」を想像しながらSQLを書くようになると、君の作るシステムはもっとタフになるはずだよ。
また何か詰まったら、いつでも聞きに来てくれ。一緒に深掘りしていこう。
コメント