1
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?

チェックサム検査と pg_checksums, pg_stat_database の変化

Last updated at Posted at 2025-10-29

チェックサムを有効化

PostgreSQL のチェックサムはデフォルトでは無効になっています。
無効の状態でpg_stat_databaseを参照すると、チェックサムに関する列に値は入っていません。

PostgreSQL 18 から、チェックサムはデフォルトで有効となりました (記事執筆時は 17 で実施)
xia4913 さん、コメントありがとうございました!

[postgres@handson-vm02 ~]$ psql -U postgres
psql (17.6)
Type "help" for help.

postgres=#
postgres=# show data_checksums;
 data_checksums
----------------
 off     ★
(1 row)

postgres=#
postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_database where datname='postgres';
-[ RECORD 1 ]------------+------------------------------
datid                    | 5
datname                  | postgres
numbackends              | 1
xact_commit              | 5
xact_rollback            | 0
blks_read                | 86
blks_hit                 | 1637
tup_returned             | 1746
tup_fetched              | 794
tup_inserted             | 0
tup_updated              | 0
tup_deleted              | 0
conflicts                | 0
temp_files               | 0
temp_bytes               | 0
deadlocks                | 0
checksum_failures        |      ★
checksum_last_failure    |      ★
blk_read_time            | 0
blk_write_time           | 0
session_time             | 22895.304
active_time              | 0.437
idle_in_transaction_time | 0
sessions                 | 1
sessions_abandoned       | 0
sessions_fatal           | 0
sessions_killed          | 0
stats_reset              | 2025-10-27 09:46:22.842822+00

postgres=#

チェックサムを有効にするには、initdb時に -kオプションを設定するか、停止時にpg_checksumsで有効化できます。今回は後者で有効化します。

[root@handson-vm02 opc]# systemctl stop postgresql-17.service
[root@handson-vm02 opc]# sudo -u postgres /usr/pgsql-17/bin/pg_checksums --enable -D /var/lib
/pgsql/17/data
Checksum operation completed
Files scanned:   948
Blocks scanned:  2827
Files written:  0
Blocks written: 0
pg_checksums: syncing data directory
pg_checksums: updating control file
Checksums enabled in cluster     ★
[root@handson-vm02 opc]#

データを破損させる前にpg_checksumsでチェックサム検査すると下記のようになります。

[root@handson-vm02 opc]# sudo -u postgres /usr/pgsql-17/bin/pg_checksums -D /var/lib/pgsql/17
/data
Checksum operation completed
Files scanned:   948
Blocks scanned:  2827
Bad checksums:  0     ★
Data checksum version: 1
[root@handson-vm02 opc]#

pg_stat_databaseを参照すると、checksum_failuresがゼロに変化していました。

postgres=# show data_checksums;
 data_checksums
----------------
 on     ★
(1 row)

postgres=#
postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_database where datname='postgres';
-[ RECORD 1 ]------------+------------------------------
datid                    | 5
datname                  | postgres
numbackends              | 1
xact_commit              | 10
xact_rollback            | 0
blks_read                | 228
blks_hit                 | 3428
tup_returned             | 3594
tup_fetched              | 1690
tup_inserted             | 0
tup_updated              | 0
tup_deleted              | 0
conflicts                | 0
temp_files               | 0
temp_bytes               | 0
deadlocks                | 0
checksum_failures        | 0     ★
checksum_last_failure    |
blk_read_time            | 0
blk_write_time           | 0
session_time             | 62010.524
active_time              | 2.056
idle_in_transaction_time | 0
sessions                 | 2
sessions_abandoned       | 0
sessions_fatal           | 0
sessions_killed          | 0
stats_reset              | 2025-10-27 09:46:22.842822+00

データを破損させる

データを破損させるテーブル (checksumtest) を作成し、テーブルのファイルパスをpg_relation_filepathで確認します。

postgres=# create table checksumtest as select generate_series(1,100000) id;
SELECT 100000
postgres=#
postgres=#
postgres=# \dt
            List of relations
 Schema |     Name     | Type  |  Owner
--------+--------------+-------+----------
 public | checksumtest | table | postgres
(1 row)

postgres=# 
postgres=# select pg_relation_filepath('public.checksumtest');
 pg_relation_filepath
----------------------
 base/5/32816
(1 row)

postgres=#

PostgreSQL を停止し、先ほど確認したファイルに手を加えデータを破損させます。

[root@handson-vm02 opc]# systemctl stop postgresql-17.service
[root@handson-vm02 opc]# su - postgres
Last login: Mon Oct 27 09:48:44 GMT 2025 on pts/0
[postgres@handson-vm02 ~]$ printf '\xFF' | dd of="/var/lib/pgsql/17/data/base/5/32816" bs=1 s
eek=$((8192*1+100)) conv=notrunc status=none
[postgres@handson-vm02 ~]$

pg_checksums, pg_stat_database の変化

pg_checksumsでチェックサム検査すると下記のようになります。
データを破損させたファイルで、チェックサムが不一致となっていることがわかります。

[root@handson-vm02 opc]# sudo -u postgres /usr/pgsql-17/bin/pg_checksums -D /var/lib/pgsql/17/data
pg_checksums: error: checksum verification failed in file "/var/lib/pgsql/17/data/base/5/32816", block 1: calculated checksum DC78 but block contains 72F8     ★
Checksum operation completed
Files scanned:   951
Blocks scanned:  3279
Bad checksums:  1     ★
Data checksum version: 1
[root@handson-vm02 opc]#

PostgreSQL を起動してpg_stat_databaseを参照すると、この時点ではチェックサムに関する列に変化はありません。

[root@handson-vm02 opc]# systemctl start postgresql-17.service
[root@handson-vm02 opc]# su - postgres
Last login: Mon Oct 27 09:52:29 GMT 2025 on pts/0
[postgres@handson-vm02 ~]$
[postgres@handson-vm02 ~]$ psql -U postgres
psql (17.6)
Type "help" for help.

postgres=#
postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_database where datname='postgres';
-[ RECORD 1 ]------------+------------------------------
datid                    | 5
datname                  | postgres
numbackends              | 1
xact_commit              | 26
xact_rollback            | 0
blks_read                | 439
blks_hit                 | 8017
tup_returned             | 8580
tup_fetched              | 3126
tup_inserted             | 100014
tup_updated              | 0
tup_deleted              | 0
conflicts                | 0
temp_files               | 0
temp_bytes               | 0
deadlocks                | 0
checksum_failures        | 0     ★
checksum_last_failure    |       ★
blk_read_time            | 0
blk_write_time           | 0
session_time             | 212789.04
active_time              | 113.807
idle_in_transaction_time | 0
sessions                 | 3
sessions_abandoned       | 0
sessions_fatal           | 0
sessions_killed          | 0
stats_reset              | 2025-10-27 09:46:22.842822+00

postgres=#

データを破損させたテーブルを参照するとエラーとなりました。
データを破損させたファイルで、チェックサムが不一致となっていることがわかります。
(pg_checksumsで検査した時と同様。但し、チェックサムの表示に10進数 (56440) と16進数 (DC78) の差あり)

また、pg_stat_databaseを参照すると、チェックサムに関する列の値が更新されています。

postgres=#
postgres=# select count(1) from checksumtest;
WARNING:  page verification failed, calculated checksum 56440 but expected 29432
ERROR:  invalid page in block 1 of relation base/5/32816
postgres=#
postgres=#
postgres=# select * from pg_stat_database where datname='postgres';
-[ RECORD 1 ]------------+------------------------------
datid                    | 5
datname                  | postgres
numbackends              | 1
xact_commit              | 29
xact_rollback            | 1
blks_read                | 516
blks_hit                 | 8263
tup_returned             | 9805
tup_fetched              | 3251
tup_inserted             | 100014
tup_updated              | 0
tup_deleted              | 0
conflicts                | 0
temp_files               | 0
temp_bytes               | 0
deadlocks                | 0
checksum_failures        | 1     ★
checksum_last_failure    | 2025-10-27 09:55:21.071478+00     ★
blk_read_time            | 0
blk_write_time           | 0
session_time             | 251541.228
active_time              | 115.365
idle_in_transaction_time | 0
sessions                 | 3
sessions_abandoned       | 0
sessions_fatal           | 0
sessions_killed          | 0
stats_reset              | 2025-10-27 09:46:22.842822+00

再度、データを破損させたテーブルを参照すると、pg_stat_databaseのチェックサムに関する列の値が更新されました。

postgres=# select count(1) from checksumtest;
WARNING:  page verification failed, calculated checksum 56440 but expected 29432
ERROR:  invalid page in block 1 of relation base/5/32816
postgres=# select * from pg_stat_database where datname='postgres';
-[ RECORD 1 ]------------+------------------------------
datid                    | 5
datname                  | postgres
numbackends              | 1
xact_commit              | 30
xact_rollback            | 2
blks_read                | 517
blks_hit                 | 8264
tup_returned             | 10031
tup_fetched              | 3251
tup_inserted             | 100014
tup_updated              | 0
tup_deleted              | 0
conflicts                | 0
temp_files               | 0
temp_bytes               | 0
deadlocks                | 0
checksum_failures        | 2     ★
checksum_last_failure    | 2025-10-27 09:55:48.2888+00     ★
blk_read_time            | 0
blk_write_time           | 0
session_time             | 278758.529
active_time              | 116.449
idle_in_transaction_time | 0
sessions                 | 3
sessions_abandoned       | 0
sessions_fatal           | 0
sessions_killed          | 0
stats_reset              | 2025-10-27 09:46:22.842822+00

postgres=#

チェックサムを有効化すると検索に一定のオーバーヘッドが生じますが、データが破損しても早期に検出することができるため、可能な限り有効にしておきましょう :smiley:

1
0
2

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
1
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?