# CHAPTER 11: ダーティリード と チェックサム

## 11.1 はじめに

Empressは、 潜在的に汚れた状態のデータを提供し、 ロックに関係なくEmpressデータベースから データを読む込むことを許可する ダーティリード機能を提供します。 （「潜在的に汚れた状態のデータ」とは例えば 別のトランザクションにより更新されているが、 まだコミットされていないデータなどを指します。）

Empressダーティリード機能は 通常のEmpressの操作のためのロック機構を 任意の方法または手段での変更はしません。 ダーティリードが指定されなければ、通常のロックのまま適用されます。 （ロック機構自体を変更するわけではないということです。） ダーティリードは、知りたがりで忙しいユーザーのために リードロック箇所をバイパスすることを 可能するためのオプションを付加するだけです。 また、ダーティリードは特権を無視しません。

ダーティリードは Empressデータベースから読み込まれたデータの確認と 検証するためにチェックサムを 使うことができ、データがこれらの確認テストに失敗した場合、 適切な動作を行います。 これはチェックサムの切り替えをするための `ALTER TABLE` コマンドと チェックサムの結果により、ダーティリードの行動を制御するための `MSVALIDATELEVEL`変数によって管理されます。

チェックサムがデータ確認のために設定された場合、 レコードのチェックサムは、それが挿入される際に合わせて 計算され、登録されます。 また、レコードの更新時においても行われます。

Empressがチェックサムでの問題を検出した場合、

- `不適切な可変長データ`メッセージは 可変長アトリビュート (例えば、`TEXT`, `NLSTEXT`, `BULK`) のオーバーフローファイル(つまり`.dtf`ファイル) で問題が見つかった場合に出力されます。
- `不適切なレコード` メッセージはメインテーブルファイル(つまり`.rel` ファイル)で問題が見つかった場合に出力されます。

チェックサムに問題がある場合おいて、 それが参照できるできないにかかわらず、 データを参照するためのオプションを提供します。

ダーティリードとチェックサムの特徴は互いに補足し合いますが、、 それらは独立して機能することができます。

## 11.2 ダーティリード・ユーザー仕様

ダーティリードはすべてのEmpressデータベースインターフェースで有効です。

- Empress SQL と Empress リポートライター

  ダーティリードはEmpress SQLにキーワード`BYPASS_LOCK`を 付加します。 ユーザーは以下のようなクエリから簡単にできます。

         SELECT BYPASS_LOCK * from table_name;

  これはロックをバイパスしたレコードの検索します。

- Empress API

  mx、mf および mrルーチンにおいて、 テーブルオープンの３つのモードがあります。

  - `r` リードモード
  - `u` アップデートモード
  - `d` デファードモード

  ダーティリードはテーブルオープンに２つの新しいモードを加えます。

  - `n` ダーティリードモード
  - `N` ダーティデファードモード

  例えば

         mxopen ("db_name", "table_name1", "n");
         mxopen ("db_name", "table_name2", "N");

  "n" モードでオープンされたテーブルは、 検索が`mxget`/`mrget` またはそれに相当するルーチンを通して 実行された場合、すべてのロックをバイパスし、レコードを検索します。 この場合においては更新操作は失敗します。

  "N" モードでオープンされたテーブルは、実際はアップデートモードでオープンされます。 更新・挿入・削除操作が実行された場合、通常のロック動作が適用されますが、 検索が`mxget`/`mrget` またはそれに相当するルーチンを通して 実行された場合、すべてのロックをバイパスしたデータを取得します。

  埋め込みスタティクSQLや埋め込みダイナミックSQLの カーソル操作の場合、カーソル宣言において キーワード`BYPASS_LOCK`を含んだクエリを指定します。 更新操作のためのオープンではない場合、カーソルのオープンの際に "n" モードで対応したテーブルをオープンします。 それ以外はテーブルは "N" モードでオープンされます。

  テーブルを明示的にオープンする場合、例えば

         EXEC SQL OPEN_TABLE table_name FOR BYPASS_LOCK;

  これは"N"モードでテーブルをオープンし、その後のすべての カーソル宣言では、テーブルを再オープンしません。

- Empress 4GL

  Empress 4GL内でダーティリードを使用するためには、 以下のコマンドを使い、ダーティリードモードでテーブルを オープンする必要があります。

         OPEN table_name BYPASS_LOCK [AS tabinst]

## 11.3 チェックサム・ユーザー仕様

チェックサムは`ALTER TABLE`コマンドによって設定されます。 (Empress SQL リファレンス マニュアルの `ALTER TABLE` を参照してください。)

テーブルのチェックサムが有効であれば、 `DISPLAY ALL`コマンドを使い、参照することができます。 例えば

       DISPLAY loans ALL;

は、以下のような出力を生成します。

       *** Table: loans ***

       Attributes:
         number                integer
         name                  character(25,1)
         date                  date(1)
         amount                dollar(6,1)

       System Attributes:
        EMPRESS_CHECK_SUM                 longinteger

       Creator: joe
       Lock Level: RECORD
       Property: varchecksum

       Table Type:  normal

       Table #: 19
       Records: 12
       Record size: 40

システムアトリビュート `EMPRESS_CHECK_SUM` は、 テーブルがチェックサムのレコードを持っていることを示します。

プロパティ`varchecksum`は、 テーブルが可変のチェックサムを持っていることを示します。

## 11.4 ダーティリード・システム変数

ダーティリードに関する3つのシステム変数があります。 これらの変数は、`$EMPRESSPATH/config/initfile`ファイル中にあり、 他のすべてのEmpress変数と同じように コマンドラインからユーザー変数内へ、また `$EMPRESSPATH/config/initfile`ファイル内に、 あるいは対話型 SQLセッション内で 設定することができます。 以下はこれらのシステム変数の説明です。

表 11-1: ダーティリード・システム変数

変数 | 説明
`MSVALIDATELEVEL` | この変数は メインテーブルファイル(つまり `.rel`ファイル)および オーバーフローファイル(つまり `.dtf`ファイル)を 読む込む場合とボーダーレコードを読み込む場合の ダーティリードの動作を制御します。 （「ボーダーレコード」は後に説明します。）
`MSVALIDATERETRY` | この変数は、Empressが無効なレコードを読み込む際のリトライ数を指定します。 すべてのリトライが終了した後にまだ不正である場合、 不正なレコードをユーザーに届けるかまたは捨てるかは `MSVALIDATELEVEL`変数の設定によります。
`MSVALIDATESLEEP` | この変数は、Empressが不正なレコードを読むための リトライ間のスリープのインターバル秒数を指定します。

### 11.4.1 MSVALIDATELEVEL

`MSVALIDATELEVEL`の値は `XYZ`の形式の３つの数字になり、 それぞれの数字は以下のケースでのダーティリードの動作を定義します。 （デフォルトは`440`です。）

- 数字 `X` は、メインテーブルファイル(つまり `.rel`ファイル)の 読み込みを制御します。
- 数字 `Y` は、オーバーフローファイル(つまり `.dtf`ファイル)の 読み込みを制御します。
- 数字 `Z` は、 ボーダーレコードの読み込みを制御します。

ダーティリードの特別なケースとしてボーダーレコードがあります。 ボーダーレコード は、ディスクブロックの境界をまたがった メインテーブルファイル（つまり`.rel`ファイル)のレコードです。 例えば、ディスクブロックサイズが1024バイトの場合、 メインレコードのサイズが正確に1024バイトか 512 バイトおよび 256 バイトなどのような 1024バイトの約数である場合はボーダーレコードではなく、 これ以外のすべてはボーダーレコードになります。 システムは、他の隣接したブロック（レコードの残りを含むブロック)から 分かれた１ブロック（レコード部分が含まれた）をフラッシュすることができ、 そのため、ロックは設定されません。 ダーティリードは、この状況を避けるためにボーダーレコードを ロックするためのオプションを提供します。 ボーダーレコードのロックはチェックサムの確認がない時に特に有用です。

数字`X`の値とこれらの説明を以下に示します。

  0 | 無効なレコードは放棄し、ダーティリードの検索でのみチェックサムデータの 確認を使います。
  1 | 無効なレコードを放棄せず、ダーティリードの検索でのみチェックサムデータの 確認を使います。
  2 | 無効なレコードは放棄し、 ダーティリードの検索および通常の検索 でチェックサムデータの確認を使います。
  3 | 無効なレコードを放棄せず、 ダーティリードの検索および通常の検索 でチェックサムデータの確認を使います。
  4 | 無効なレコードを放棄せず、 ダーティリードの検索および通常の検索で チェックサムデータの確認を使いません。

数字`Y`の値とこれらの説明を以下に示します。

  0 | 無効な可変長データを放棄し、 ダーティリードの検索でのみチェックサムデータの 確認を使います。 無効な`TEXT`アトリビュートには、すべて空白の文字列と 無効な`BULK`アトリビュートにはすべてゼロのデータが 格納されています。
  1 | 無効な可変長データを放棄せず、 ダーティリードの検索でのみチェックサムデータの 確認を使います。
  2 | 無効な可変長データを放棄し、 ダーティリードの検索および通常の検索でチェックサムデータの 確認を使います。 無効な`TEXT`アトリビュートにはすべて空白の文字列と 無効な`BULK`アトリビュートにはすべてゼロのデータが 格納されています。
  3 | 無効な可変長データを放棄せず、 ダーティリードの検索および通常の検索でチェックサムデータの 確認を使います。
  4 | 無効な可変長データを放棄せず、 ダーティリードの検索および通常の検索でチェックサムデータの 確認を使いません。

数字`Z`の値とこれらの説明を以下に示します。

  0 | `0`がセットされたとき、すべてのボーダーレコードは `SELECT BYPASS_LOCK`が実行されている間、ロックされません。
  1 | `1`がセットされたとき、 `SELECT BYPASS_LOCK`が実行されている間、 すべてのボーダーレコードにリードロックが設定されます。

### 11.4.2 MSVALIDATERETRY

`MSVALIDATERETRY`は、Empressが無効なレコードを読む際の リトライ数を指定します。 すべてのリトライが終了した後にまだ不正である場合、 不正なレコードをユーザーに届けるかまたは捨てるかは `MSVALIDATELEVEL`変数の設定によります。

`MSVALIDATERETRY` のデフォルト値は 10 です。 不正なレコードである場合、 レコードの確認テストでパスするかどうかチェックするために 10回までのリトライが行われるということ意味します。

### 11.4.3 MSVALIDATESLEEP

Empressが不正なレコードを読むための リトライ間のスリープのインターバル秒数を `MSVALIDATESLEEP`に指定します。

`MSVALIDATESLEEP`のデフォルト値は 0.09 です。 Empressが、リトライの間 9 ミリ秒スリープすることを意味します。

## 11.5 ダーティリード特権

ダーティリードは、データベース特権として新たな特権タイプを追加しています。 `BYPASS_LOCK`と呼ばれる特権でユーザー特権グループの１つになります。 `BYPASS_LOCK`特権は、テーブルへの`SELECT BYPASS_LOCK`を ユーザーに許可します。 この機能は許可されていないユーザーがロックされたレコードを読むことを防ぎます。 この特権をもつことにより、トランザクションにおいて 他のユーザによりロックされている中間のレコードを読むこと において大変役に立ちます。

## 11.6 エラーコードとエラーメッセージ

ダーティリードとチェックサムの ２つの新しいエラーコードとメッセージを紹介します。

1. `"不正なレコードが返されました。"` 不正なレコードが検索されたときにエラーが起こります。

   - mr ルーチン

     mrの場合、`mroperr`に`MRERBADRECORD`設定されます。 In the case of mr routines, `mroperr` is set to `MRERBADRECORD`. 不正なレコードを含むすべてのレコードを検索するために `MSVALIDATELEVEL`が設定された場合、 正常な場合は`mrget`は`1`を返し、エラーの場合は`-1`を返します。 不正なレコードが検索されたときに `mrerrmsg`ルーチンはエラーとして "不正なレコードが返されました。" を返します。

   - 対話型 SQL

     `MSVALIDATELEVEL`に 不正なレコードを含むすべてのレコードを検索するための設定をした場合、 不正なレコードがユーザーに返されときに以下のメッセージを出力します。

            *** Warning *** 読み込みエラー　不正なレコードが返されました。

     `MSVALIDATELEVEL`に正常なレコードだけ返すように設定した場合は、 不正なデータが見つかるたびに以下のメッセージを出力します。

            *** Warning *** 不正なレコードが返されました。レコードを読み飛ばします。

   - 埋め込み SQL

     埋め込みスタティクSQL と 埋め込みダイナミックの場合、 `"SQLCODE"`に `"-10"`が設定され、 `"SQLERRMC"`には`"Error -10: 読み込みエラー　不正なレコードが返されました。"` が設定されます。

   - Empress 4GL スクリプト言語

     Empress 4GL スクリプト言語の `"error_number"`に`"2017"`がセットされ、 `"got_records"`変数には "1"、 エラーメッセージは "不正なレコードが返されました。"が設定されます。

   - Empress GUI ビルダー スクリプト言語

     Empress GUI ビルダーの `"sqlcode"`変数は、`2015`が設定され、 `"sqlresult"`は、"1"、 "sqlmessage"には、"不正なレコードが返されました。"が設定されます。

2. `"不正な可変長の値が返されました。"` 不正な可変長の値が検索された場合にエラーが起こります。

   - mr ルーチン

     mrルーチンの場合、`mroperr`に`MRERBADDATARETR`が設定され、 `mrerrmsg`ルーチンは、次のエラーメッセージ が返されます。"不正な可変長の値が返されました。"

     対話型 SQL `MSVALIDATELEVEL`に 不正な可変長アトリビュートの検索をするための設定をした場合、 不正なレコードがユーザーに返されときに以下のメッセージを出力します。

            *** Warning *** 読み込みエラー　不正な可変長の値が返されました。

     `MSVALIDATELEVEL`に、上記以外の設定がされた場合、 不正なテキストアトリビュートは空白で埋められ、また 不正なバルクアトリビュートはゼロで埋められます。 両方とも以下のメッセージを伴ってユーザーに返されます。

            *** Warning *** 読み込みエラー 不正な可変長の値が返されました。

   - 埋め込み SQL

     埋め込みスタティクSQL と 埋め込みダイナミックの場合、 `"SQLCODE"`に `"-10"`が設定され、 `"SQLERRMC"`には`"Error -10: 読み込みエラー　不正な可変長の値が返されました。"` が設定されます。

   - Empress 4GL スクリプト言語

     Empress 4GL スクリプト言語の `"error_number"`に`"2018"`がセットされ、 `"got_records"`変数には "1"、 エラーメッセージは "不正な bulk/text の値が取り出されました。"が設定されます。

   - Empress GUI ビルダー スクリプト言語

     Empress GUI ビルダーの `"sqlcode"`変数は、`2016`が設定され、 `"sqlresult"`は、"1"、 "sqlmessage"には、"不正な bulk/text の値が取り出されました。"が設定されます。

   注意：マニュアル中の日本語のエラーメッセージですが、意味自体は同じですが、 実際のメッセージと多少、表現が異なるメッセージを返すことがありますのでご注意ください。 例えば、マニュアル中では、"不正なレコードが返されました。"と示しましたが、 "不正なレコードが取り出されました。"と返される場合もあります。