[hackers-jp: 72] Re: Fw: Re: [HACKERS] PITR Dead horse?

井久保 寛明 ikuboh @ nttdata.co.jp
2004年 2月 6日 (金) 17:33:12 JST


井久保です。

急ににぎやかになりましたね。

On Wed, 04 Feb 2004 15:49:04 +0900
Satoshi Nagayasu <snaga @ snaga.org> wrote:

> > > 本家のスレッドはどこから追ったらいいんでしょう?
> >
> > http://archives.postgresql.org/pgsql-hackers/2002-07/msg00164.php
> > あたりがスタートです。もう1年以上前か・・・
> 
> ありがとうございます。ちょっと追ってみます。

私もお勉強開始です。

退路が断たれようが、背水の陣であろうが、急に英語力が増すわけでも
ないので、地道なことやってみました。
# 私が断つべきものは、日本語かなぁ...。


とりあえず、上記URL の部分ですね。
################################################################################

Issues Outstanding for Point In Time Recovery (PITR)

--------------------------------------------------------------------------------

From: "J. R. Nield" <jrnield ( at ) usol ( dot ) com> 
To: PostgreSQL Hacker <pgsql-hackers ( at ) postgresql ( dot ) org> 
Subject: Issues Outstanding for Point In Time Recovery (PITR) 
Date: 04 Jul 2002 11:45:49 -0400 

--------------------------------------------------------------------------------

Hello:

ロギングシステムによって、システムのシャットダウンした一貫性のあるコピーを
取ることができ、複数のチェックポイントとおして、後方に向けて実行することが
できることを理解した。
これは、CREATE TABLE/DROP TABLE/TRUNCATE の機能も扱うことができ、そして、
後方に向けてうまく実行ができる。任意の point-in-time へのリカバリは、簡単に
できる。しかし、そのための管理インタフェースが必要になる。

さて、私がこれをどのように実装すればいいかということに意見を頂きたい。

最も重要な疑問点は、セクション 2 と 5 である。なぜなら、システム全体に
影響を与えるからである。また、これらについて、システム管理者のための優
れたドキュメントも要求されるだろう。

Issues Outstanding for Point In Time Recovery (PITR)

    $Date: 2002/07/04 14:23:37 $

    $Revision: 1.4 $

    J.R. Nield

    (Enc: ISO 8859-15 Latin-9)


§0 - Introduction

    このファイルは、PTIRを実装する間に出てきた全ての問題点をトラッキング
    するためのものである。できれば、PITRが実装された後は、どのようにPITR
    が動くのかということを詳細に説明するドキュメントに発展させたい。

    フィードバックをもらったら、そのつど反映させるつもりである。

    現時点の大きな問題は次のようなものである:
        §1 - リレーションファイルの記録、切詰め、削除
	    これは、ほとんど実現されている。オンラインログから無限に
	    後方へ進めることができる。
        §2 - 部分的な書き出しと不良ブロックの検出
	    開始前の入力の必要性。移行の問題。
            Need input before starting. Migration issues.
        §3 - シャットダウンされた状態の一貫性を持つシステムリカバリの検出
            ほとんど実現されている。
        §4 - システム全体のインタラクティブなロールフォワードリカバリ。
	    開始前に、入力を必要とする
        §5 - 個々のファイルの一貫性のあるリカバリ
	    入力が必要。いくつかの中規模の変更が必要。

§1 - リレーションファイルの記録、切詰め、削除

  §1.1 - 問題点:

	ログにファイルを作成が書かれていないと、リレーションを作成したコミット
	済みのトランザクションを再実行することができない。

	現状のコードでは次のことを仮定している。コミットまでたどりついたトラン
	ザクションは、ファイルが存在することが保証されている。そして、それらの
	ファイルは決して削除されることはない。現在これは正しい。しかし、DBの古
	いバックアップから、ログを使った再実行では、うまくいかない。

	現在のXLOGのコードは、存在しないファイルに対するブロック書き出し要求を
	暗黙のうちに無視する。そして、そういうリクエストを出すトランザクション
	は、アボートされていると仮定している。

	現在、TRUNCATE TABLE 中のクラッシュは、そのテーブルを一貫性のない状態
	のままにする(部分的な切詰めが行われている)。これは、最後のチェックポイ
	ントより前から再実行するとき、機能しない。

    §1.1.1 - CREATE DATABASE もログを取らずに実行する

	これは、再実行の際に、上に書いたのと同じ問題を引き起こす

  §1.2 - 提案:

     a) リレーションファイルの操作をロギングし、redo 要求を適切に扱えるよう
	に、SMGRのコードを増強する。CREATE の場合は非常に簡単である。DROP は
	コミットレコードの中にだけ記録されていなければならない。TRUNCATE は
	(b) を参照。

	f_smgr 構造体は、新しい操作 smgr_recreate, smgr_reunlink, smgr_retruncate
	が必要になる。smgr_recreate は、Relation の代わりに RelFileNode を受け付け
	られるようにする必要がある。

	システム障害でアボートしたトランザクション(つまりログを書かずにアボー
	トしたトランザクション)は、単にファイルがリークするだけである。
	# つまり無駄なファイルが残ったままになる

     b) もし TRUNCATE TABLE が失敗したらシステムは PANIC で終了しなければならない。
	さもなければ、そのテーブルは将来のコマンドで使用され、再実行してリカバリ
	したDBは、オリジナルと異なったデータになるかもしれない。

	WALは、ファイルの切詰め前にフラッシュされなければならない。

	もし、しばしば無駄なファイルが残ることを気にしなければ、WALは ファイル作
	成前にフラッシュする必要はない。

     c) Redo コードは、存在しないファイルに対する書き出しをエラーとして扱わなけ
	ればならない。
	変更点は、heap, nbtree のアクセスメソッドに影響を与える。[他も要チェック]

     d) rtree [GiST も?] は、ログをとっていない。再実行によるデータベースのリカ
	バリは、全てのrtree のインデックスを壊れているという扱いにしなければなら
	ない。 [実際、今やるべき?]

     e) CREATE DATABASE は、適切にログを取らなければならない。system(cp ...) を
	使ってはならない。

  §1.3 - ステータス:

	全てのロギングの必要な SMGR の操作は、START_CRIT_SECTION()/END_CRIT_SECTION()
	の間に入っている。XLogInsert() とファイルシステムの操作が隠蔽されている。

	smgr と xact モジュールにログを取るためのコードを追加した:
		create (no XLogFlush)
		truncate (XLogFlush)
		削除は、コミットレコードまで延期する
		アボートレコードがあったらファイルの削除を行う

	md.c に redo の操作のためのコードを追加した

	smgr に RMGR の redo/desc コールバックのコードを追加した

	xact に RMGR の redo/desc コールバックのコードを追加した。

	もし、手動でコントロールファイルのステータスをDB_SHUTDOWNEDの代わりに
	DB_IN_PRODUCTION に設定することができれば、データベースは、オンライン
	ログから、シャットダウン一貫性のあるシステムリカバリを無限に実行できる
	だろう。

	まだ、やらなければならないこと:
		(c) で、全てのアクセスメソッドで、リカバリでクリーンナップ処理の実装
		(d) で、他のインデックスのアクセスメソッドのロギングの実装
		(e) で、CREATE DATABASE の実装


§2 - Partial-Write and Bad Block detection

  §2.1 - 問題点:

	ログを書いていないページに対して部分的な書き出しを2回行うことを防ぐ
	ため、システムファイルの部分的なページを検出して、それらをシステム管
	理者に通知する必要がある。メモリ破壊やOSのエラーなど、他の原因で壊れ
	たページを検出したいということもある。また、ディスクが不良ブロックを
	報告しないで、おかしなデータを返すようなケースも考えられる。

	壊れてたページを持っているという印が付けられたファイルを見つけたとき、
	何をするかを決めなければならない。そして、バックアップからのログアー
	カイブリカバリが求められる。

  §2.2 - 提案:

	PageHeaderData に1バイトの pd_flags を追加する。その定義は次の
	とおりである。

	        PD_BLOCK_CHECKING           (1)
	        PD_BC_METHOD_BIT            (1<<1)

	        PageHasBlockChecking(page)     ((page)->pd_flags & PD_BLOCK_CHECKING)
	        PageBCMethodIsCRC64(page)      ((page)->pd_flags & PD_BC_METHOD_BIT)
	        PageBCMethodIsLSNLast(page)    (!PageBCMethodIsCRC64(page))


	ページの最後の64ビットは、ブロックチェックコードのために利用する。

	[ ページのブロックチェックがオフのときに、各ページの最後8バイトを無駄に
	  使用する価値はある?
	  この提案では、これは許していない。 ]

	ブロックのチェックに CRC64 を使うなら、最後8バイトのフィールドには、
	書込み時にそのブロックのCRC64を計算して、入れておく。

	もしブロックチェックの方法が LSNLast なら、pd_lsn フィールドの複製を
	入れておく。

    §2.2.1 - ページハンドリングのルーチンを変更する

	全てのページハンドリングのルーチンは、
	pd_special == (pd_special - (specialSize + 8))
	というように変更しなければならない。

	これを反映するために、bufpage.h のヘッダのコメントを修正する。

    §2.2.2 - ページの読み込み時

	CRC64を使うと、ブロック読み込み時にブロックが壊れているかどうか明確に
	検出できる。

	LSNLast の場合は、そのページの最後の64ビットが pd_lsn と同じかどうか
	チェックする。もし異なれば、そのページは部分書き込みで壊れていると
	仮定する。(しかし、違う場合があるかもしれない)

	重要な仮定: 
	OSやディスクデバイスが、真ん中を飛ばしてブロックの先頭と最後を書き込む
	ことがあってはならない。これが起こるとうまくいかない場合が出てくる。

    §2.2.4 - GUC 変数

	ユーザがどの方法を使うか設定できるようにする

		block_checking_write_method  = [ checksum | torn_page_flag | none ]

	どの方法を使うべきだろうか?

		check_blocks_on_read      = [ true | false ]

	true の場合、どの方法が選択されていても、ブロックが壊れていないか
	読み込み時に選択する。
	false の場合は、ブロックチェック情報を無視する。

  §2.3 - ステータス:

	pgsql-hackers からの回答待ち

    質問:
	もっと細かいレベルで、ユーザがブロックチェック機能を制御できるように
	するべきだろうか?

	例えば、全てのデータベースの全てのシステムカタログで、チェックサムを
	使えるようにして、torn_page_flag を生成したデータベースのシステム
	カタログ以外に設定できるようにして、none をその他の全てに設定するなど

§3 - シャットダウンされた状態の一貫性を持つシステムリカバリの検出

    §3.1 - 問題点:

	リストアされたコントロールファイルにシャットダウンチェックポイントレコ
	ードを示す情報を保存するときに、システムのバックアップ(ファイル?)に対
	してログを再実行する必要があることを知らせる方法が問題である。
	コントロールファイルは、最新のチェックポイントレコードをログに書く前に
	書き込まれる。また、コントロールファイルの指す先は、アーカイブファイル
	でもよい。

    §3.2 - 提案:

	スタートアップ時には、コントロールファイルを読んだ後、アクティブログ
	ファイルのリストを取得するためにログディレクトリをスキャンし、ファイル
	の最小の logId と logSeg を見つける。ファイルは、連続した範囲のLSN を
	カバーしていることを保証する。

	次の3つの場合がある:

	1) コントロールファイルは、最後の有効なチェックポイントを指している。
	   (checkPoint または prevCheckPoint である。しかし、どちらかがログ
	   ストリーム中の最大の有効なチェックポイントレコードである)

	2) コントロールファイルは、アクティブなログファイルの有効なチェック
	   ポイントを指している。しかし、それよりも後ろの有効なチェックポイ
	   ントレコードがある
	3) コントロールファイルは、アーカイブログにあるべきチェックポイント
	   レコードを指している。そして、多分それは有効である。

	(1) の場合は、今扱うべきである。
	(2), (3) の場合は、ロールフォワードリカバリを行うための準備として、
	バックアップからのシステム全体をリストアする結果に含まれる。

	行うべきことは:

	(2), (3) の場合を検出する。

	管理者にアラートを上げ、スタートアップを中止する。

	[疑問点: いつもこういう動きでいいのだろうか? (2)の場合は、管理者の
	 仲介なしに処理ができる]

	管理者は、スタンドアロンバックエンドを起動し、システムのロールフォワ
	ードリカバリを実行する。

    §3.3 - ステータス:

	進行中

§4 - システム全体のインタラクティブなロールフォワードリカバリ

	バックアップファイルからのファイルのロールフォワードリカバリは、インタラ
	クティブでなければならない。なぜなら、全ての必要なログファイルがアーカイ
	ブログディレクトリにあるとは限らないからである。もしかしたら、全てのアー
	カイブログファイルは、1度にディスクに入らないかもしれない。

	システムは、プロンプトを出して、システム管理者に次のログファイルを
	入れるように要求できる必要がある。

	TODO: ここにはたくさんある。

§5 - 個々のファイルの一貫性のあるリカバリ

  §5.1 - 問題点:

	もし、ファイルが壊れているのを検出して、バックアップからリストア
	するとき、どのアーカイブファイルがリカバリに必要かをどうやって
	知るかが問題である。

	部分的な書き出しや不良ブロックなどで壊れたファイルをシステムカタログ
	から外し、システムをアボートさせるべきか、または、単にそのリレーション
	だけまたは、そのDBだけをオフラインにすべきだろうか?

	与えられたバックアップファイルに対して、壊れたファイルのリカバリを
	開始する場所をどのようにして決定するのだろうか? 壊れたファイルを
	完全に修復できる最も大きいLSNはどうやって決めればいいのだろうか?

  §5.2 - 提案: 
	各ファイルにファイルヘッダを置く。そして、最低、file_lsn_time_slack 
	分毎に、ヘッダファイルの最終チェックポイントの LSN を更新する。
	または、少なくとも dbsize/'file_lsn_log_slack' MBのログが書き込まれ
	たら1回更新する。ここで、dbsize は、データベースサイズの見積もり
	サイズである。これらの値は、コンフィグファイルから設定できるようにする。
	これらのヘッダの更新は、時間、または、一定量のログ生成のタイミングを
	利用して分散される。

	データベースバックアップのコマンドを実行したら、バックアップを開始
	する前に、安全であることを保証できる最も大きな値(LSN?)に、ヘッダを
	更新する。

  §5.3 - ステータス:

	pgsql-hackers の返事待ち

    質問:
	バックアップファイルからリカバリするための開始場所の下限を知るための
	正しいと判っている LSN を得るためにファイルヘッダを使う方法以外にも、
	いくつか方法がある。
	一番いい方法はなんだろうか?

A) 定義
	この定義は、あいまいだが言いたいことをはっきりさせるためのものである。
	このドキュメントでは、一貫してこの定義を使う。

    "up to date" or "now" or "current" or "current LSN":

	1つの $PGDATA ディレクトリ以下にある PostgreSQL のデータベースの
	集まりのことである。これは、同時に1つの postmaster インスタンスに
	よって扱われる。(そして1つのWAL ログを持っている)

	これらのシステムを構築するファイルは、1つのグループとして扱う

    "up to date" or "now" or "current" or "current LSN":

	システムの一番新しい永続的なLSN
        The most recent durable LSN for the system.

    "block consistent copy":

	1つのファイルに対して使う場合:

	ファイルのコピーで、コピー処理中に書き込みがあってもいいが、
	各BLCKSZのサイズのブロックごとのコピーは、アトミックに行われた
	もの。

	(同じシステムで)ファイルに対して使う場合:

	全てのファイルのコピーで、それぞれは 独立に "block consistent copy"
	である。

    "file consistent copy":

	1つのファイルに対して使う場合:

	ファイルのコピーで、コピー処理の開始と終了の間に書き込みがないもの。

	(同じシステムで)ファイルに対して使う場合:

	全てのファイルのコピーで、個々のファイルが独立に "file consistent copy"
	を満たしているもの。

    "system consistent copy":

	1つのファイルに対して使う場合:
        
	ファイルのコピーで、コピー処理中にシステム全体で、そのメンバーの
	ファイルが1つも書込み処理を行われていないもの

	(同じシステムで)ファイルに対して使う場合:

	全てのファイルのコピーで、全てのファイルのコピー処理の開始から
	終了まで書き込みが行っていないもの。

    "shutdown consistent copy":

	1つのファイルに対して使う場合:

	ファイルのコピーで、コピー処理の開始時点からコピーが終わるまで、
	システム全体がきれいにシャットダウンされている状態のものである。

	(同じシステムで)ファイルに対して使う場合:

	全てのファイルのコピーで、全てのファイルがコピー処理の開始時点から
	コピーが終わるまで、システム全体がきれいにシャットダウンされている
	状態のものである。

    "consistent copy":

	block consistent copy, file consistent copy, system consistent copy,
	shutdown consistent copy の総称

    "known-good LSN lower bound" 
    or "LSN lower bound"
    or "LSN-LB":

	ブロックのグループ、1つのファイル、ファイルの集まりに対して使う場合:

	ファイルやブロックを最新の状態にするために、十分古くてそれより前には
	必要な情報を持っていないことを保証できる LSN のこと。

    "known-good LSN greatest lower bound" 
    or "LSN greatest lower bound" 
    or "LSN-GLB":

	ブロックのグループ、1つのファイル、ファイルの集まりに対して使う場合:

	そのグループに対して必要な変更が、これより上にはないと言うことがわかって
	いる最大のLSN のこと。

    "backup file":

	システムで使われるデータファイルの一貫性のあるコピー。
	"a known-good LSN lower bound" (下限)の状態のもの。

    "optimal backup file":

	バックアップファイルで、"the known-good LSN greatest lower bound"(最大のLSN)
	が反映されているもの。

    "backup system":
        


    "Play-Forward File Recovery" or "PFFR":

	個々のバックアップファイルを最新の状態にする処理
        
-- 
J. R. Nield
jrnield ( at ) usol ( dot ) com

################################################################################



---
井久保 寛明 (Hiroaki Ikubo)
NTTデータ先端技術 (株) オープンソース技術部
E-mail: ikubo @ intellilink.co.jp (E-mail: ikuboh @ nttdata.co.jp)





hackers-jp メーリングリストの案内