PostgreSQL 高度技術者育成テキスト ch5 (障害対応)
LPI-Japan OSS-DB Gold 認定教材 PostgreSQL 高度技術者育成テキスト
- 作者:河原 翔
- 発売日: 2014/10/27
- メディア: オンデマンド (ペーパーバック)
障害対応の基本
- 理想的な流れ
- 事象を確認する
- 状況を把握/整理する
- 目標を定める
- 対応案を検討する
- 対応を施す
- 効果を確認する
- 【所感】不具合修正と同じ
- 現象を再現する
- 落ちるテストを書く
- 状況の把握・整理
- 目標を定める = どこまで直すか
- 修正を施す
- 修正を確認する
- テストが通ること
サーバダウン障害への対応
PostgreSQLが起動できない
事象
- PostgreSQLが起動できない
状況把握
- ログ
- プロセス
主な原因・対処案
メモリ不足
- postgresql.confの
shared_buffers
がカーネルパラメータshmmax
を超えると、PostgreSQLサーバ起動時に怒られる kernel.shmmax
が16GB、shared_buffers
が32GBの例
... 2020-02-02 17:10:40.948 UTC [97] FATAL: could not map anonymous shared memory: Cannot allocate memory 2020-02-02 17:10:40.948 UTC [97] HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 35207938048 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections. 2020-02-02 17:10:40.948 UTC [97] LOG: database system is shut down stopped waiting pg_ctl: could not start server Examine the log output.
- 適切な値を設定する
データベースクラスタの権限設定ミス
~$ initdb data2 ~$ chmod 770 data2 ~$ pg_ctl start -D data2 -o "-p 5433"
waiting for server to start....2020-02-29 11:20:16.530 UTC [145] FATAL: data directory "/var/lib/postgresql/data2" has invalid permissions 2020-02-29 11:20:16.530 UTC [145] DETAIL: Permissions should be u=rwx (0700) or u=rwx,g=rx (0750). stopped waiting pg_ctl: could not start server Examine the log output.
- 700にしようね
動作不良
事象
- 接続できない
- 問い合わせに対する応答がない
状況把握
- ログ
- プロセス
- そもそもOSやNWで止まっていないか?
- timeoutかrefusedかの切り分けとか
主な原因
接続できない系
- 名前解決できてない
psql -h hoge
psql: error: could not connect to server: could not translate host name "hoge" to address: Name or service not known
- 名前解決できているが、当該ホストの指定のポートでサーバが動いていない
psql -p 5433
psql: error: could not connect to server: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5433"?
- 当該ポートでサーバが動いているが、host based authenticationに引っかかっている
psql -U syaro -d postgres
psql: error: could not connect to server: FATAL: pg_hba.conf rejects connection for host "[local]", user "syaro", database "postgres", SSL off
- 対処案
- L4までのレベルでの接続可否の確認
- 設定見直し
接続できているが処理が帰ってこない系
リソース枯渇
事象
- PostgreSQLがクラッシュ停止する
状況把握
- ログ確認
主な原因
- セマフォ不足
- ディスク容量不足
- wal領域がディスクフルになるとpanic
- メモリ不足
対処案
- 設定見直し
- カーネルパラメータ含む
- リソース追加
データ消失と復旧
バックアップからのリカバリ
- 略
トランザクションログ復旧
事象
- トランザクションログの破損/消失が原因でPostgreSQLが起動できなくなる
再現
- 壊す用のデータベースクラスタ作る
initdb data2 pg_ctl -D data2 start -o "-p 5433" pg_ctl -D data2 stop
- WALセグメントの先頭256Bを0で埋めて壊してみる
dd conv=notrunc if=/dev/zero of=data2/pg_wal/000000010000000000000001 bs=256 count=1
1+0 records in 1+0 records out 256 bytes copied, 0.0001245 s, 2.1 MB/s
- サーバが立ち上がらなくなる
pg_ctl -D data2 start -o "-p 5433"
waiting for server to start....2020-02-29 12:23:30.692 UTC [840] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit 2020-02-29 12:23:30.692 UTC [840] LOG: listening on IPv4 address "0.0.0.0", port 5433 2020-02-29 12:23:30.692 UTC [840] LOG: listening on IPv6 address "::", port 5433 2020-02-29 12:23:30.696 UTC [840] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5433" 2020-02-29 12:23:30.711 UTC [841] LOG: database system was shut down at 2020-02-29 12:21:37 UTC 2020-02-29 12:23:30.711 UTC [841] LOG: invalid primary checkpoint record 2020-02-29 12:23:30.711 UTC [841] PANIC: could not locate a valid checkpoint record 2020-02-29 12:23:30.711 UTC [840] LOG: startup process (PID 841) was terminated by signal 6: Aborted 2020-02-29 12:23:30.711 UTC [840] LOG: aborting startup due to startup process failure 2020-02-29 12:23:30.712 UTC [840] LOG: database system is shut down stopped waiting pg_ctl: could not start server Examine the log output.
状況把握
- ログ
主な原因
- トランザクションログの破損/消失
対処案
pg_resetwal
コマンドでトランザクションログを復旧する- 決して手で操作しようとか思わないこと
pg_resetwal -D data2
Write-ahead log reset
- サーバ起動
pg_ctl -D data2 start -o "-p 5433"
- 無事起動した
waiting for server to start....2020-02-29 12:27:25.357 UTC [851] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit 2020-02-29 12:27:25.357 UTC [851] LOG: listening on IPv4 address "0.0.0.0", port 5433 2020-02-29 12:27:25.357 UTC [851] LOG: listening on IPv6 address "::", port 5433 2020-02-29 12:27:25.362 UTC [851] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5433" 2020-02-29 12:27:25.375 UTC [852] LOG: database system was shut down at 2020-02-29 12:27:10 UTC 2020-02-29 12:27:25.381 UTC [851] LOG: database system is ready to accept connections done server started
pg_resetwal
pg_resetwal resets the PostgreSQL write-ahead log. Usage: pg_resetwal [OPTION]... DATADIR Options: -c, --commit-timestamp-ids=XID,XID set oldest and newest transactions bearing commit timestamp (zero means no change) [-D, --pgdata=]DATADIR data directory -e, --epoch=XIDEPOCH set next transaction ID epoch -f, --force force update to be done -l, --next-wal-file=WALFILE set minimum starting location for new WAL -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID -n, --dry-run no update, just show what would be done -o, --next-oid=OID set next OID -O, --multixact-offset=OFFSET set next multitransaction offset -V, --version output version information, then exit -x, --next-transaction-id=XID set next transaction ID --wal-segsize=SIZE size of WAL segments, in megabytes -?, --help show this help, then exit Report bugs to <pgsql-bugs@lists.postgresql.org>.
トランザクションIDを変更する例
pg_xact/
ディレクトリを確認し、最も大きな数字をもつファイル名を調べる- PostgreSQL9.x系では
pg_clog/
- PostgreSQL9.x系では
ls -lA pg_xact/
total 8 -rw------- 1 postgres postgres 8192 2020-02-29 21:32 0000
- これに1を足して、1048576 = 2^20 = (2^4)^5 を掛ける
- 16進数ならばゼロを5つつければよい
0x0000 -> 0x0001 -> 0x000100000
- この値に設定する
pg_resetwal -x 0x100000 data2
Write-ahead log reset
システムテーブルのインデックス復旧
事象
- システムテーブルのインデックスが破損し、PostgreSQLが正常に動作しない
再現
- データベースのoid特定
oid2name -p 5433
All databases: Oid Database Name Tablespace ---------------------------------- 13408 postgres pg_default 13407 template0 pg_default 1 template1 pg_default
- データベースオブジェクトのoid特定
oid2name -p 5433 -d postgres -i -S
From database "postgres": Filenode Table Name --------------------------------------------------------- 2600 pg_aggregate 2650 pg_aggregate_fnoid_index 2601 pg_am 2651 pg_am_name_index 2652 pg_am_oid_index ...
pg_class_oid_index
を壊してみる
2662 pg_class_oid_index
- ページファイル確認
ls -lA base/13408/2662
-rw------- 1 postgres postgres 32768 2020-02-29 21:21 base/13408/2662
- 先頭256Bに0を書き込んで壊してみる
dd conv=notrunc if=/dev/zero of=data2/base/13408/2662 bs=256 count=1
- サーバ停止・起動
pg_ctl -D data2 stop pg_ctl -D data2 start -o "-p 5433"
- 接続を試みる
psql -p 5433
- 壊れていて接続できない
- ので
REINDEX
も実行できない
- ので
2020-02-29 12:58:53.917 UTC [3494] FATAL: invalid page in block 0 of relation base/13408/2662 psql: error: could not connect to server: FATAL: invalid page in block 0 of relation base/13408/2662
状況把握
- ログ
2020-02-29 12:58:53.917 UTC [3494] FATAL: invalid page in block 0 of relation base/13408/2662 psql: error: could not connect to server: FATAL: invalid page in block 0 of relation base/13408/2662
対処案
- 下記のいずれかでPostgreSQLを起動する
- シングルユーザ状態
-P
オプションつきでpostmaster
起動
- システムインデックスを無視する状態
ignore_system_indexes
パラメータをON- 開発者向けオプションなので
postgresql.conf
のコメントアウトには無い
- 開発者向けオプションなので
- シングルユーザ状態
- 前者を実施してみる
pg_ctl -D data2 stop pg_ctl -D data2 start -o "-p 5433 -P" cat postmaster.opts
/usr/lib/postgresql/12/bin/postgres "-D" "data2" "-p" "5433" "-P"
psql -p 5433
- 接続できた
psql (12.1 (Debian 12.1-1.pgdg100+1)) Type "help" for help. postgres=#
- oid2nameで壊れたデータベースオブジェクトを特定
oid2name -p 5433 -o 2662
From database "postgres": Filenode Table Name ------------------------------ 2662 pg_class_oid_index
pg_class_oid_index
をREINDEX
する
REINDEX (VERBOSE) INDEX pg_class_oid_index;
INFO: index "pg_class_oid_index" was reindexed DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s REINDEX
- 通常のオプションでPostgreSQL再起動
pg_ctl -D data2 stop pg_ctl -D data2 start -o "-p 5433"
- 接続確認
psql -p 5433
- 接続できるようになった
psql (12.1 (Debian 12.1-1.pgdg100+1)) Type "help" for help. postgres=#
レプリケーション・ホットスタンバイ復旧
散々やったので略
障害対応向けオプション
- 公式/開発者向けオプション
ignore_system_indexes
- onにすると、システムテーブルを読むとき、インデックスを無視する
- システムカタログのインデックスが破損して接続できなくなったときなどに
- onにすると、システムテーブルを読むとき、インデックスを無視する
zero_damaged_pages
- onにすると、破損したページを0埋めして、最低限のデータをサルベージできるようにする
- 埋められた部分のデータは当然失われる
- バックアップを取っていなかった・バックアップも失われた場合などに
- onにすると、破損したページを0埋めして、最低限のデータをサルベージできるようにする