【IRIS/Cache】ジャーナル(上級編)

本記事はグローバル・ジャーナル(上級編)についての解説になります。

※この記事は下記の方向けになります。
  • ジャーナルの操作をロジック上で行いたい方
  • 実践的なジャーナル操作を行いたい方
  1. はじめに
  2. %SYS.NOJRN.incの利用
    1. ジャーナルの制御
    2. 他の停止・開始コマンド
      1. ジャーナル停止
      2. ジャーナル再開
      3. ジャーナルの状態確認
      4. ジャーナルの開始/停止
  3. %SYS.Journal.File.clsの利用
      1. ジャーナルのパージ
  4. %SYS.Journal.System.clsの利用
    1. Queries
      1. ジャーナルファイルの進捗確認
      2. ジャーナルシステムの状態確認
      3. ジャーナルシステムの設定確認
    2. ジャーナルシステムの制御関連
      1. ジャーナル開始
      2. ジャーナル停止
      3. ジャーナルの切り替え
      4. ジャーナルの切り替え
      5. ディレクトリの切り替え
    3. ジャーナルシステムの情報取得
      1. WIJに保存されているジャーナルチェックポイント情報を返す
      2. プライマリジャーナルディレクトリのパスを返す
      3. セカンダリジャーナルディレクトリのパスを返す
      4. クラスタジャーナルログのパスを返す
      5. 最新のジャーナルファイル・オブジェクトを返す
      6. ジャーナルファイルのファイル数を返す
      7. 最新のジャーナルファイルのパスを返す
      8. 最新のジャーナルファイルのオフセット値を返す
      9. 不明
      10. ジャーナルファイル名のプリフィックスを返す
      11. 最後のジャーナルファイルのパスを返す
      12. ジャーナルシステムの状態を返す
      13. ジャーナルシステムの状態を返す(ステータスを文字列で返す)
      14. 現在のディレクトリではない方のディレクトリを返す
    4. ジャーナルシステムの状態確認
      1. システム全体でジャーナルが無効になっているか確認する
      2. システム全体でジャーナルがフリーズしているか確認する
      3. システムが回復しようとしているジャーナリングエラーがあるか確認する
      4. システム全体でジャーナルが一時停止しているか確認する
    5. ジャーナルシステムへの設定
      1. プライマリ・ジャーナルディレクトリの設定
      2. セカンダリ・ジャーナルディレクトリの設定
  5. ジャーナルファイルに目印を付ける
  6. おわりに

はじめに

前回の記事では、ターミナルを利用してのジャーナル操作をご紹介いたしました。

本記事では、クラスやルーチン上でジャーナルの操作を行っていこうと思います。

それでは、クラスを作成し、ジャーナル操作を始めましょう。

%SYS.NOJRN.incの利用

ジャーナルの制御

%SYS.NOJRNルーチンを使用する事で、プロセス間でジャーナルの停止/出力を制御する事が可能です。
 ※他のプロセスではジャーナルの制御は行われません。

下記がサンプルになります。

ClassMethod jorStop(mode As %Boolean = 0)
{
	// 出力を停止する
	d:mode DISABLE^%SYS.NOJRN
	
	k ^test
	s ^test = "テスト"_$zdt($now(),3,1,6)
	
	s obj = ##class(developer.data.Patient2).%OpenId(1)
	w obj.漢字氏名
	s obj.漢字氏名 = "埼玉 タケ"_$now()
	d obj.%Save()
	
	// 出力を再開する
	d:mode ENABLE^%SYS.NOJRN
		
	
	k ^sample
	s ^sample=$zdt($now(),3,1,6)
	
	s obj = ##class(developer.data.Patient2).%OpenId(3)
	w obj.漢字氏名
	s obj.漢字氏名 = "栃木 ウメ"_$now()
	d obj.%Save()
}

ターミナルから関数を実行すると、ジャーナル停止区間のデータ更新が、ジャーナリングされていない事が確認できます。

他の停止・開始コマンド

似たようなコマンドがあるので併せて紹介します。

ジャーナル停止

各コマンドは、最終的にコマンド「DISABLE^%SYS.NOJRN」を呼んでいます。
なので↓のコマンドは、そこまで使わなくても良いかなーって感触です。

d STOP^%SYS.NOJRN
w $$STOP^%SYS.NOJRN // 1:ジャーナル停止

d DisableJournal^%SYS.NOJRN
w $$DisableJournal^%SYS.NOJRN

ジャーナル再開

現在使用している「$roles」が%All以外である場合、$ETRAPをクリアする等々の処理を実行します。
それ以外は、コマンド「ENABLE^%SYS.NOJRN」を実行するだけです。

d EnableJournal^%SYS.NOJRN

ジャーナルの状態確認

w $$CURRENT^%SYS.NOJRN // 1:ジャーナル開始, 0:ジャーナル停止

ジャーナルの開始/停止

引数によって停止と開始を制御可能。
 ※このコマンドは、「DISABLE」も「ENABLE」も呼ばない。

// ジャーナル停止
w $$SetJournal^%SYS.NOJRN(0)

// ジャーナル開始
w $$SetJournal^%SYS.NOJRN(1)

%SYS.Journal.File.clsの利用

ジャーナルのパージ

ジャーナルファイルの削除を実施します。

s sts = ##class(%SYS.Journal.File).Purge([NDaysOld],[NBackupsOld])

NDaysOld : 指定日数を経過したジャーナルを削除する(作成日ではなく完了日基準)
NBackupsOld : 「この回数のバックアップ成功後」

両引数は、管理ポータルのジャーナル設定画面の↓の設定になります。

トランザクションのロールバックまたはクラッシュ回復に必要なジャーナル ファイルを除き、すべてのジャーナル ファイルを消去します。

s sts = ##class(%SYS.Journal.File).PurgeAll()

%SYS.Journal.System.clsの利用

Queries

このクラスのカスタム・クエリは、「SQLProc」が付与されていないため「%ResultSet」を使用した実行方法しか行えません。

ただ、クラスの編集自体は可能なので、任意にSQLProcを付与してSQLとして実行する事は可能です。

ジャーナルファイルの進捗確認

下記サンプルは、コマンドを実行後ジャーナルの状態を60秒おきに確認します。
 ※明確な停止を行わない限り、ずっとループし続けます。

rowNo列名説明
1File Nameジャーナルファイル名(フルパス)
2File Countジャーナルファイルのファイル数
ジャーナルファイルを切り替える度にカウントアップしている。
3offsetジャーナルのオフセット値
4offset Committed不明…
5TimeStamp確認した時刻(GMT)
ClassMethod Progress()
{
	s rs=##class(%ResultSet).%New("%SYS.Journal.System:Progress")
	d rs.Execute()
	while rs.Next() {
		w "Name:",rs.Data("File Name"),!
		w "Count:",rs.Data("File Count"),!
		w "Offset:",rs.Data("Offset"),!
		w "Offset Committed:",rs.Data("Offset Committed"),!
		w "TimeStamp:",$zdt($SYSTEM.Util.UTCtoLocalWithZTIMEZONE(rs.Data("TimeStamp")),3,1,6),!!
		
		h 60
	}
}

ジャーナルシステムの状態確認

下記サンプルは、コマンドを実行後ジャーナル・システムの状態を60秒おきに確認します。
 ※明確な停止を行わない限り、ずっとループし続けます。

ClassMethod Status()
{
	s rs=##class(%ResultSet).%New("%SYS.Journal.System:Status")
	d rs.Execute()
	while rs.Next() {
		w "Main Status:", rs.Data("Main Status"),!
		w "Cause:", rs.Data("Cause"),!
		w "Full Status:", rs.Data("Full Status"),!!
		
		h 60
	}
}

ジャーナルシステムの設定確認

ClassMethod Summary()
{
	new $namespace
	s $namespace = "%SYS"
	
	s rs=##class(%ResultSet).%New("%SYS.Journal.System:Summary")
	d rs.Execute()
	w !,rs.GetColumnHeader(1),?40," ",rs.GetColumnHeader(2),!
	while rs.Next() { w !,rs.Data("Parameter"),?40," ",rs.Data("Value") }
}

出力例

ジャーナルシステムの制御関連

クラス「%SYS.Journal.System」には、中級編で紹介したコマンドと同様の機能を有する関数がいくつか存在しています。

中級編と同様の機能ではありますが、異なる点として対話型になっていないため、実行時にシステムから確認等が求められません。

対話型ではないため、実行前にコマンドや引数等を念入りに確認する必要がありますが、バッチ処理等に組み込むには丁度良いと思います。

※全てのコマンドは%SYSネームスペースで実行して下さい。

ジャーナル開始

ジャーナルを開始します。既に開始している場合はエラーとなります。

w ##class(%SYS.Journal.System).Start()
w ##class(%SYS.Journal.System).Start(curdir, altdir, maxsiz, expsiz, prefix, okshdw)

関数「Start」実行時に下記を引数とすることで、ジャーナルシステムの設定を変更する事が可能です。

引数名説明
curdirプライマリ・ジャーナルパス
altdirセカンダリ・ジャーナルパス
maxsizジャーナルファイルの最大サイズ
expsizジャーナルファイルの増加量
prefixジャーナルファイルのプリフィックス
okshdwファイルの競合が発生する可能性があっても、シャドウ ジャーナル ファイルとディレクトリを共有する

ジャーナル停止

ジャーナルを停止します。既に開始している場合はエラーとなります。

w ##class(%SYS.Journal.System).Stop()

ジャーナルの切り替え

処理内で、関数「RollToNextFile」を呼んでいる。
ただジャーナルを切り替えるだけであれば、次に紹介する「RollToNextFile」でも十分です。

w ##class(%SYS.Journal.System).SwitchFile()
w ##class(%SYS.Journal.System).SwitchFile(curdir, altdir, maxsiz, expsiz, okshdw, reason)

関数「SwitchFile」実行時に下記を引数とすることで、ジャーナル・システムの設定を変更する事が可能です。
 ※Startと一部重複するため割愛します

引数名説明
reason切り替え時の説明
省略すると管理ポータルのジャーナル画面に「指定されていません」と表示される。

■下記数値から選択する
0 or null:指定されていません
1:ユーザにより
2:ファイルサイズの上限に到達
3:失敗したI/Oの再試行をするため
4:バックアップにより
5:リストアにより
6:タスクマネージャにより
7:ジャーナル設定変更を有効にするため
8:ジャーナルを再度有効にするため
9:ミラースタートアップにより
10:ミラーシャットダウンにより
11:ミラーデータベースが削除されました
12:UNKNOWN:12
13:ディレクトリテーブルを拡張するには
以下:UNKNOWN:[reason値]

ジャーナルの切り替え

ジャーナリングを次のファイルに変更します

w ##class(%SYS.Journal.System).RollToNextFile(reason, .newFile),!
w newFile,!

ディレクトリの切り替え

切り替えが成功した後、現在のジャーナル ファイルのパスをNewFileに格納する

w ##class(%SYS.Journal.System).SwitchDirectory(.newFile),!
w newFile

ジャーナルシステムの情報取得

コマンドは全て%SYSネームスペースで実行して下さい。

WIJに保存されているジャーナルチェックポイント情報を返す

w ##class(%SYS.Journal.System).GetImageJournalInfo(.JournalFileName, .JournalFileOffset, .JournalFileCount, .OpenTransFileOffset, .OpenTransFileCount)
w JournalFileName,!
w JournalFileOffset,!
w JournalFileCount,!
w OpenTransFileOffset,!
w OpenTransFileCount,!

プライマリジャーナルディレクトリのパスを返す

w ##class(%SYS.Journal.System).GetPrimaryDirectory(.sts),!
w sts

セカンダリジャーナルディレクトリのパスを返す

w ##class(%SYS.Journal.System).GetAlternateDirectory(.sts),!
w sts

クラスタジャーナルログのパスを返す

w ##class(%SYS.Journal.System).GetClusterJournalLog()

最新のジャーナルファイル・オブジェクトを返す

obj : %SYS.Journal.File.cls

s obj = ##class(%SYS.Journal.System).GetCurrentFile()
w obj.Name

ジャーナルファイルのファイル数を返す

w ##class(%SYS.Journal.System).GetCurrentFileCount()

最新のジャーナルファイルのパスを返す

w ##class(%SYS.Journal.System).GetCurrentFileName()

最新のジャーナルファイルのオフセット値を返す

ジャーナリングがオフの場合は0を返す

w ##class(%SYS.Journal.System).GetCurrentFileOffset()

不明

ジャーナルファイルに使用可能な空き領域を返すらしい・・・

w ##class(%SYS.Journal.System).GetFreeSpace()

ジャーナルファイル名のプリフィックスを返す

w ##class(%SYS.Journal.System).GetJournalFilePrefix()

最後のジャーナルファイルのパスを返す

w ##class(%SYS.Journal.System).GetLastFileName()

ジャーナルシステムの状態を返す

w ##class(%SYS.Journal.System).Status()
ステータス値説明
0有効
1無効 (停止)
2一時停止 (I/O エラーのため)
3フリーズ (I/O エラーのため)
4一時停止 (ジャーナル ファイルの切り替え中)

ジャーナルシステムの状態を返す(ステータスを文字列で返す)

w ##class(%SYS.Journal.System).GetStateString()

日本語の場合、$$$Textで下記変換が行われる

ステータス値($$$Text変換)本来の戻り値説明
正常Normal有効で正常に実行中
無効Disabled停止中
一時停止SuspendedI/O エラーのため
凍結FrozenI/O エラーのため
一時停止Pausedジャーナル ファイルの切り替え中

現在のディレクトリではない方のディレクトリを返す

w ##class(%SYS.Journal.System).GetTheOtherDirectory(.Directory, .Type)
w Directory,!
w Type,!
Typeの値説明
1プライマリ・ジャーナルディレクトリ
2セカンダリ・ジャーナルディレクトリ
0他にディレクトリがない

ジャーナルシステムの状態確認

システム全体でジャーナルが無効になっているか確認する

w ##class(%SYS.Journal.System).IsDisabled()

システム全体でジャーナルがフリーズしているか確認する

w ##class(%SYS.Journal.System).IsFrozen()

システムが回復しようとしているジャーナリングエラーがあるか確認する

w ##class(%SYS.Journal.System).IsGettingIOError()

システム全体でジャーナルが一時停止しているか確認する

w ##class(%SYS.Journal.System).IsPaused()

ジャーナルシステムへの設定

プライマリ・ジャーナルディレクトリの設定

w ##class(%SYS.Journal.System).SetPrimaryDirectory(dir, create)

セカンダリ・ジャーナルディレクトリの設定

w ##class(%SYS.Journal.System).SetAlternateDirectory(dir, create)

ジャーナルファイルに目印を付ける

ジャーナルファイルに目印(マーカ)を入力する事が出来ます。
デバッグ用などに利用すると便利です。

引数「id(%Integer)」「テキスト(%String)」は自由に設定が可能です。

zn "%SYS"
w $$ADD^JRNMARK([id], [テキスト])

// 例
w $$ADD^JRNMARK(4649, "よろしく!")

ジャーナルファイルにマーカを設定できます。

おわりに

いかがだったでしょうか。

処理上でジャーナルファイルを操作する場合は、対話のない処理が必要になります。

中級編では、対話型でのジャーナル操作を行いましたが、上級編ではユーザへのアクションが無いため、処理の成功/失敗は必ず確認する必要があります。

ジャーナル操作を処理に組み込む必要がある場合は、この記事を参考にして下さい。