チェックサムを有効化
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=#
チェックサムを有効化すると検索に一定のオーバーヘッドが生じますが、データが破損しても早期に検出することができるため、可能な限り有効にしておきましょう ![]()