2008年7月18日金曜日

OSの時間変更における影響について

Oracle 上で OS のシステム日時に変更があった場合には
下記のことが発生すると考えられます。

Oracle は時間情報を更新履歴のファイルと
各ファイル(制御ファイル、データファイル、REDO ログ)内に持っています。

* OS の時間を進める場合
特に問題は発生しないと考えられます。 
* OS の時間を遅らせる場合
o 時間指定でのリカバリができなくなる。
+ OracleはREDOログにタイムスタンプを持っています。
このタイムスタンプはトランザクション実行時のシステム時刻が
ベースとなっています。時間ベースのリカバリでは、
リカバリ指定時刻より未来のタイムスタンプが現れた時点でREDOの適用は
終了します。
o 未来に作成された表などをアクセスできなくなる。
+ 未来の作成日時を持つオブジェクトにアクセスすると、
ORA-1466が発生してデータを読み込むことができません。
CONSISTENT=Yでのエクスポートについても
内部的にSET TRANSACTION READ ONLY文が実行されますので、
同様の状況が発生する可能性があります。
o SYSDATE を使用したアプリケーションが正常に動作しなくなる。
+ SYSDATE関数はシステム時刻をもとに値を返しますので、
システム時刻の変更によりユーザ・アプリケーション、
ユーザ・データの整合性に影響を及ぼす可能性があります。
o ジョブ・キュー・プロセスによって実行されるジョブが正常に動作しなくなる。
+ ジョブ・キュー・プロセス(SNP)によって実行されるジョブは、
システム時刻をもとにスケジュールされています。
ユーザが作成しスケジュールしたジョブばかりでなく、
マテリアライズド・ビュー(スナップショット)の自動リフレッシュや
遅延トランザクションの伝播等でもジョブ・キューは使用されています。
ジョブが実行されるタイミングに関して十分な考慮が必要となります。

但し、ミリ秒単位で戻すのは問題ないようです。
内部は秒単位で管理しているようです。
また、時間を通常より遅く進めても構わないようです。
但し、OS 時間で1秒間に SCN
(System Change Number : COMMIT する都度、
増加する数)が16,000以上増加させる事はできません。

Oracle ではインスタンス起動中での、
OS のシステム日時の変更はサポートされていません。
また、インスタンス停止中であってもシステム日時を戻すことは、
「OS の時間を遅らせる場合」の状況が発生する場合がある可能性があります。

システム時間を整合性を持って戻すには、データベースを停止し、
システム時刻を戻した後、データベースを停止した時点のシステム時刻になるまで
データベースを起動しない。のが一番良いと思います。

上記のことから、

構成

* クラスタを構築したシステムでは、外部との時間同期を行わない。
あくまでノード間でのみ時刻を同期させる。
(外部の時刻源に合わせて、クラスタ内の時間が進んだり、戻ったりすることが発生するから。)
* Windows Time(W32Times) の時刻源となるサーバを自分自身とする。
具体的には、コマンド・プロンプトから
 net time /setsntp:サーバ名 と入力する。
設定を確認するのは
 net time /querysntp と入力すると設定されている SNTP サーバ名が表示される。
o 但し、私の環境下では SNTP サーバを設定しても、
W32Time がイベントにエラーを吐いているのは消えなかったので、
net time の設定は削除しました。
予測ですが、このサーバは PDC FSMO ではないため、
自分自身の W32Time から見て、 SNTP サーバの役目を行っていないためだと思います。
自分自身を時刻源として設定できるのは、
自分が PDC FSMO でないとできないかと考えられます。
また、 Windows Time のサービス自体を止めてしまおうかと考えましたが、
Windows Time サービスに依存しているサービスとして
"Cluster Service"が存在したので停止できませんでした。
現状でも、このエラーは出ている状態です。
* 「タイム・リソース・サービス」を保有するノード上に Oracle の DB を構築する。
(時刻源であるノード上にあれば、Oracle の時間の戻りは発生しないと考えられる。)
* フェィル・オーバ、フェィル・バックが発生しても、
「タイム・リソース・サービス」で同期を取っているので、
問題は発生しないと考えられる。
(微妙に時間のずれが発生する可能性はあるが、特に問題は出ないと考えられる。)

時間の合わせ方

1. Oracle のインスタンスを停止させる。
(Oracle 保持しているクラスタ・グループをオフラインにする。)
2. 「タイム・リソース・サービス」を保有しているノードの時間を合わせる。
(手動で「net time」のコマンド等を使用して、外部の時刻源と時間を合わせる。)
3. 別のノードの時間を「net time」のコマンドを使用して、
「タイム・リソース・サービス」を保有しているノードに合わせる。
NET TIME \\サーバ名 /set /y

OS の時間を進める場合は問題ないと考えられるが、
OS の戻す場合には Oracle のインスタンスを停止させた後、
あるポイントでの時刻を記録し、その時刻を基準となる時刻が越えてから時刻合わせを行う。
4. Oracle のインスタンスを起動する。
(Oracle 保持しているクラスタ・グループをオンラインにする。)

大規模なサーバ環境下では、それなりのサーバを使用しており、
それなりのハードウェア・クロックを内蔵しており、
また、温度管理のされたマシンルーム等に設置されていると思われるので、
システム時間が大幅にずれてくることは少ないと思います。
その為、半年程度に1回程度、合わせるのが現実的かと思います。