2013年12月15日

【9.3新機能チェック】データチェックサムの機能とパフォーマンスへの影響

このエントリは、PostgreSQL Advent Calendar 2013のDay15の記事です。

データベース管理システムにとって、「データを保護する」というのは非常に重要な役割のひとつです。

PostgreSQLには、9.3から「データチェックサム」という機能が追加されました。これは、ハードウェア障害などによってデータが壊れた時に、そのことを極力早期に検出しよう、という仕組みです。

今回は、このデータチェックサムについて、その仕組みと使い方、性能への影響について紹介します。

■「データチェックサム」とは

「データチェックサム」というのは、PostgreSQLのデータブロック内のデータのチェックサムのことで、PostgreSQLのデータブロックの中身が万が一壊れた時に、早期に検出できるようにするための仕組みです。

9.2まではこの機能が無かったため、「(メモリやディスク不良が起因で)データブロックの中身が壊れていることにかなり後になって気付く」ということもありました。

というのは、各ブロック内部のタプル(あるいはタプルヘッダ)のデータが一部壊れているような場合、「そのタプルにアクセスしてみないとデータが正常かどうか分からないし、場合によってはスルーされてしまう」ということも多かったためです。

9.3以降は、このデータチェックサムを使えばかなり早期に検出できるようになります。

具体的に見てみましょう。PostgreSQLのデータブロックは8kb単位となっていますが、そのブロックの先頭部分には「ページヘッダ」と呼ばれる管理情報の領域があります。



「データチェックサム」はこのページヘッダの中に pd_checksum メンバとして保持されています。(なお、データチェックサムは16ビットのunsigned int型の整数値となっており、pg_checksum_page() で計算されます。)
typedef struct PageHeaderData
{
    /* XXX LSN is member of *any* block, not only page-organized ones */
    PageXLogRecPtr pd_lsn;      /* LSN: next byte after last byte of xlog
                                 * record for last change to this page */
    uint16      pd_checksum;    /* checksum */
    uint16      pd_flags;       /* flag bits, see below */
    LocationIndex pd_lower;     /* offset to start of free space */
    LocationIndex pd_upper;     /* offset to end of free space */
    LocationIndex pd_special;   /* offset to start of special space */
    uint16      pd_pagesize_version;
    TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
    ItemIdData  pd_linp[1];     /* beginning of line pointer array */
} PageHeaderData;
チェックサムは、ページデータをディスクブロックに書き出す時に計算されて、上記のページヘッダのメンバーとしてディスクに書き出されます。

逆に、ディスクブロックを読み込んだ時には、該当するページデータから計算できるチェックサムと、ページヘッダに保持されているチェックサムが同じであることを確認することで、ページデータが壊れていないことを確認することになります。

■データチェックサムを有効にするには

データチェックサムは、PostgreSQLのデータベースクラスタ初期化時に、有効にするかどうかを指定します。後から設定を変更することはできないのでご注意ください。

具体的には initdb に -k オプションを付けてデータベースクラスタを作成すると、データチェックサムが有効になります。
[snaga@devsv03 checksum]$ initdb --no-locale -E UTF-8 -D /pgsql/checksumtest/data -k
The files belonging to this database system will be owned by user "snaga".
This user must also own the server process.

(...)

Data page checksums are enabled.

fixing permissions on existing directory /pgsql/checksumtest/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
(...)
[snaga@devsv03 checksum]$ 
initdb実行時に「Data page checksums are enabled.」と出力されたら、データチェックサムが有効になります。「Data page checksums are disabled.」と出たら無効です。

また、作成済みのデータベースクラスタでチェックサムが有効になっているかどうかは pg_controldata コマンドで確認することができます。
[snaga@devsv03 checksum]$ pg_controldata /pgsql/checksumtest/data | grep -i checksum
Data page checksum version:           1
[snaga@devsv03 checksum]$ 
この「Data page checksum version」が「1」になっていればデータチェックサムが有効、「0」になっていたら無効になっています。

詳細はマニュアルを参照してください。

■データチェックサムでエラーを検出すると

データチェックサムでエラーを検出すると、PostgreSQLは以下のような警告とエラーメッセージを出力します。
WARNING:  page verification failed, calculated checksum 18672 but expected 19809
ERROR:  invalid page in block 14935 of relation base/16455/24220
上記のメッセージは、OID 16455に該当するデータベースの、relfilenodeが24220に該当するファイルの、14935ブロックのデータが壊れている(データチェックサムが19809であるべきなのに18672になっている)ということを意味しています。

■パフォーマンスへの影響の調査

データチェックサムは非常に便利な機能ですが、当然ながら処理が増えますので、パフォーマンスへの影響が考えられます。そこで、ベンチマークを取ってパフォーマンスへの影響を調べてみます。

テストの内容ですが、データチェックサムはブロックアクセス(ブロック読み込み、ブロック書き込み)の際に処理が行われますので、当然ながらブロックアクセスが頻発する方が影響は見やすくなります。

というわけで、
  • 共有バッファを小さくして
  • pgbenchを使って
  • スケールファクタを大きくして
  • CPUコア(スレッド)と同じ並列度で
  • SSD上で動かしてI/Oネックにならないようにして
  • 更新を伴うTPC-Bと、参照のみのSELECT-onlyで
  • 11回実行して、初回を除いた10回分を集計対象とする
というテストを実施してみました。

結果は以下の通りです。

 
上記のTPC-B、およびSELECT-onlyについて、それぞれ平均と標準偏差を見てみると、
  • TPC-B
    • チェックサムあり:平均 1,678 tps、標準偏差 279 tps
    • チェックサムなし:平均 1,638 tps、標準偏差 232 tps
  • SELECT-only
    • チェックサムあり:平均 6,180 tps、標準偏差 146 tps
    • チェックサムなし:平均 6,330 tps、標準偏差 187 tps
となりました。

上記ではTPC-Bは差が無く、SELECT-onlyの方は差があるように見えますが、それぞれの平均値についてt検定(有意水準5%)をすると
  • TPC-Bの方は有意な差があるとは言えない
  • SELECT-onlyの方は有意な差がある(チェックサムなしの方が有意に速い)と言える
という結果になります。(以下の図は、TPC-Bの結果のt検定とSELECT-onlyの結果のt検定です)


この結果を私なりに解釈すると、参照のみのトランザクションの場合は多少差が出るものの、更新処理を伴うような場合にはデータブロックアクセス以外の処理にも時間が費やされるため、データチェックサムによる処理は誤差と言えるレベルに収まる、と言えるのではないかと思います。

なお、今回の実験の詳細なログ等は、以下を参照してください。(ブロックアクセスなどの統計情報も残っています)

■まとめ

今回は、9.3で新しく実装されたデータチェックサムの機能について、その仕組み、動作とパフォーマンスへの影響を見てきました。

データチェックサムは、データベースにおいてデータを保護するためにDBAにとっては非常に重要な機能の一つです。確かにパフォーマンスに影響を与える部分が無いわけではありませんが、その影響を補って余りあるメリットがあると私自身は考えています。

ぜひ、興味のある方は9.3のデータチェックサムの機能を使ってみていただければと思います。

では、また。

0 件のコメント:

コメントを投稿