2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

postgresql で shared buffer hash table corrupted が発生した

Posted at

ローカルでの開発に docker compose を利用していて、 postgres コンテナに大量データを追加していくとSELECT を発行した時にエラーが出るようになった。

ActiveRecord::StatementInvalid: PG::InternalError: ERROR:  shared buffer hash table corrupted (ActiveRecord::StatementInvalid)

コンテナを再起動したりするとエラーにならない場合もある。
メモリ関連の値を変更すれば解消できるのではないかと考え、値を変更してみた。

※ 以下の対応で設定したメモリの値を適当なので、本番等では PostgreSQLのメモリ管理を考える を参考に計算する必要がある。

対応1 shared_buffers のサイズを増やす

現状のcomposeの設定内容と shared_buffers のサイズ。

compose.yaml
  db:
    image: postgis/postgis:12-3.1-alpine
    ...
    volumes:
      - db:/var/lib/postgresql/data:cached
❯ docker compose exec -i db psql -c 'show shared_buffers;'
 shared_buffers
----------------
 128MB
(1 row)

まずはこのdocker イメージで利用している設定ファイルをコピーする。

docker compose run -i --rm db cat /var/lib/postgresql/data/postgresql.conf > conf/postgresql.conf

shared_buffers をとりあえず倍に増やしてvolumeにマウントする。

config/postgresql.conf
- shared_buffers = 128MB                  # min 128kB
+ shared_buffers = 256MB                  # min 128kB
compose.yaml
    volumes:
      - db:/var/lib/postgresql/data:cached
+      - ./config/postgresql.conf:/var/lib/postgresql/data/postgresql.conf

再びデータを追加していくと同様のエラーが発生する。

対応2 work_mem maintenance_work_memを増やす

追加で以下の変更を行う。

config/postgresql.conf
- #work_mem = 4MB                         # min 64kB
- #maintenance_work_mem = 64MB            # min 1MB
+ work_mem = 64MB                         # min 64kB
+ maintenance_work_mem = 128MB            # min 1MB

今度はエラーの内容が少しだけ変わった。

ActiveRecord::StatementInvalid: PG::InternalError: ERROR:  shared buffer hash table corrupted (ActiveRecord::StatementInvalid)
CONTEXT:  parallel worker

なぜ並列実行されていて失敗してしまうのか根本原因がわからないが、並列実行を行わないように変更する。

config/postgresql.conf
- #max_parallel_maintenance_workers = 2   # taken from max_parallel_workers
+ max_parallel_workers_per_gather = 0    # taken from max_parallel_workers

一応これでデータは登録できた。
最終的には、 1,146,532件 を登録できた。
その後、max_parallel_workers_per_gather = 2 に戻しても特にエラーは出なかった。

まとめ

ローカルでの開発向けに、メモリ数、並列実行するを変更することでデータを投入することができた。
本番稼働を見据えて、CPUの数やコンテナに割り当てるメモリ数から postgres側のメモリを計算しておく必要がある。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?