レコードのロック

4D - Documentation   French   English   German   Spanish   日本語   4D v11 SQLコマンドテーマリスト   4D v11 SQLインデックス   4D v11 SQL定数テーマリスト   戻る   前   次

version 11 (Modified)


4Dと4D Serverは、マルチユーザまたはマルチプロセスのコンフリクトを防ぐことによってマルチユーザデータベースを自動的に管理します。2人のユーザまたは2つのプロセスが、同時に同じレコードやオブジェクトを修正することはできませんが、2番目のユーザやプロセスはレコードやオブジェクトに読み込みのみのアクセスを得ることができます。

この章のマルチユーザコマンドを使用しなければならない状況がいくつかあります:

・プログラミング言語を使用してレコードを更新する。

・マルチユーザ環境でカスタムユーザインタフェースを使用する。

・トランザクション内で関連する変更を保存する。

マルチプロセスデータベースでコマンドを使用するときに注意すべき重要な概念が3つあります:

・各テーブルは、読み込み専用または読み書き可能のどちらかに設定される。

・レコードは、ロードされた時点で他のプロセスに対しロック状態となり、アンロ−ドされた時点でロック解除になる。

・ロックされたレコードは、更新することはできない。

この章では、マルチユーザデータベースで作業を実行する人をローカルユーザと呼びます。マルチユーザデータベースを使用する他の人を他のユーザと呼びます。この節では、ローカルユーザの観点で説明します。またマルチプロセスの観点から、データベース上で処理を実行しているプロセスをカレントプロセスと呼びます。その他の実行中のプロセスは他のプロセスと呼びます。この章では、カレントプロセスの観点で説明します。

ロックされたレコード


ローカルユーザやカレントプロセスは、ロックされたレコードを更新できません。ロックされたレコードをロードすることは可能ですが、更新することはできません。他のユーザやプロセスが更新するためにレコードをロードした時点で、そのレコードはロックされます。レコードを更新しているユーザだけが、そのレコードをロックされていない状態で取り扱うことができます。その他のすべてのユーザやプロセスは、レコードがロック状態になるため更新することはできません。ロックされていない状態でレコードをロードするには、テーブルを必ず読み書き状態に設定しなければなりません。

読み込みのみと読み書き状態


データベース中の各テーブルは、データベースの各ユーザおよび各プロセスに対して読み込みのみ状態と読み書き状態のいずれかになっています。読み込みのみとは、テーブルからレコードをロードすることはできるが更新することはできないという状態です。読み書きとは、テーブルのレコードをロード可能であり、他のユーザが先にそのレコードをロックしていない場合には更新することができる状態です。

テーブルの状態を変更すると、その変更は次からロードされるレコードに影響を及ぼすことに注意してください。テーブル状態を変更する際に既にロードされていたレコードは、状態変更によって影響を受けることはありません。

読み込みのみ状態

テーブルが読み込みのみ状態に設定されると、ロードしたレコードは常に更新不可にされます。つまり、レコードの表示と印刷を実行することはできますが、更新することはできません。

この読み込みのみ状態は、既存レコードの更新処理に対してのみ適用されることに注目してください。読み込みのみ状態は新規レコードの作成に影響を与えません。デザインモードのメニューやCREATE RECORDADD RECORDを使って読み込みのみテーブルにレコードを追加することができます。

4Dは、レコードに対する書き込み動作を必要としないコマンド利用時、テーブルを自動的に読み込みのみ状態にします。以下そのコマンドを示します:

DISPLAY SELECTION

DISTINCT VALUES

EXPORT DIF

EXPORT SYLK

EXPORT TEXT

GRAPH TABLE

PRINT SELECTION

PRINT LABEL

QR REPORT

SELECTION TO ARRAY

SELECTION RANGE TO ARRAY

テーブルの現在の状態を知るには、Read only stateコマンドを使用します。

これらのコマンドを実行する前に、4Dはカレントプロセスにおけるテーブルのそのときの状態 (読み込みのみまたは読み書き) を保持します。コマンドを実行した後でテーブルの状態を元に戻します。

読み書き状態

読み書き状態のテーブルからロードされたレコードは、他のユーザがそのレコードを先にロックしていなければ更新可能になります。レコードが他のユーザによってロックされている場合にはレコードをロックされたレコードとしてロードできますが、更新はできません。

テーブルが読み書き状態に設定され、ロードしたレコードがロックされていない時に、レコードの更新が可能になります。

あるユーザが読み書き状態のテーブルからレコードをロードすると、他のユーザはレコードをロードできますが、更新することはできません。しかし他のユーザはデザインモード内での手動によるレコード追加、あるいはCREATE RECORDADD RECORDを使ってのレコード追加をすることはできます。

データベースが開かれたりまたは新規プロセスが開始された時点で、すべてのテーブルはデフォルトで読み書き状態です。

テーブル状態の変更

READ ONLYおよびREAD WRITEコマンドを使って、テーブル状態を変更することができます。あるレコードを読み込みのみ状態または読み書き状態にするために任意テーブルの状態を変更したい場合は、そのレコードをロードする前にコマンドを実行する必要があります。既にロードされたレコードは、READ ONLYおよびREAD WRITEによって影響を受けることはありません。

各プロセス毎に、データベース内の各テーブルに対する独自の状態 (読み込みのみまたは読み書き) を持っています。

レコードのロード、更新、アンロード


ローカルユーザがレコードを更新するためには、テーブルが読み書き状態でかつ、ロードしたレコードがロックされていない状態でなければなりません。

NEXT RECORD, QUERY, ORDER BY, RELATE ONE等のカレントレコードをロードするコマンドは、そのレコードをロックまたはロック解除状態にします。レコードは、テーブルのその時の状態 (読み込みのみまたは読み書き) とそのレコードの状態に応じてロードされます。自動リレートを使用するコマンドを使用した場合、リレート先テーブルからもレコードがロードされます。

テーブルが読み込みのみ状態になっている場合、そのテーブルからロードされたレコードはロックされています。他のプロセスから、ロックされたレコードの保存および削除はできません。読み込みのみの状態を使用することをお勧めします。この状態は他のユーザに対しレコードのロード、更新、保存を可能にします。

テーブルが読み書き状態になっている場合、そのテーブルからロードされたレコードは他のユーザが先にロックしていない限り更新可能になります。更新可能なレコードは、更新して保存することができます。テーブルは、レコードをロードする前に読み書き状態にしなければなりません。

レコードを修正する場合、Locked関数を使って、他のユーザがレコードをロックしていないかどうかを調べます。レコードがロックされている (LockedがTrueを返す) 場合、レコードをLOAD RECORDコマンドでロードし、そのレコードがロックされているかどうかを再び調べます。レコードがロック解除される (LockedがFalseを返す) までこの処理を繰り返します。

レコードの更新が完了したら、UNLOAD RECORDを使ってそのレコードを解放 (他のユーザに対しロック解除) しなければなりません。レコードがアンロードされないと、他のカレントレコードが選択されるまで、すべての他のユーザに対してロックされた状態のままになります。テーブルのカレントレコードを変えると、前のカレントレコードは自動的にロック解除されます。カレントレコードを変更しない場合は、UNLOAD RECORDコマンドを明示的に呼び出す必要があります。これは既存レコードの場合だけであり、新しいレコードを作成する場合、そのレコードが属するテーブルの状態に関係なく保存することができます。

Note: トランザクションの中でUNLOAD RECORDコマンドを使用した場合、トランザクションを管理するプロセス中でのみカレントレコードがアンロードされます。他のプロセスから見た場合、レコードはロックされたままとなり、トランザクションを完了 (または取消し) されるまで維持されます。

LOCKED ATTRIBUTESコマンドを使用すると、レコードをロックしているユーザやプロセスを知ることができます。

ロック解除されたレコードをロードするためのループ


以下の例は、アンロックされたレコードをロードするための最も単純なループ処理を示しています:

   READ WRITE ([Customers])   ` ーブルを読み書きに設定
   Repeat   ` レコードがアンロックされるまでループ
      LOAD RECORD ([Customers])   ` レコードをロードし、他のプロセスに対しロックする
      If (Locked([Customers]))   ` まだロックされいれば
         DELAY PROCESS (Current process;5)   ` 絶え間ないロード指示を避ける
      End if
   Until (Not (Locked([Customers])))
      ` レコードに処理を行う
   READ ONLY ([Customers])   ` ーブルを読み込みのみにする

このループ処理は、レコードがロック解除されるまで繰り返されます。

このようなループ処理は、ユーザがループが終了するまで待たされるため、レコードが他のユーザにロックされる可能性がほとんどない場合にのみ使用することができます。したがって、メソッドからのみレコードを更新するような場合以外では使用することはできません。

以下の例は先のループを使用してアンロックされたレコードをロードし、更新を行っています:

   READ WRITE([Inventory])   ` ーブルを読み書きに設定
   Repeat   ` レコードがアンロックされるまでループ
      LOAD RECORD([Inventory])   ` レコードをロードし、他のプロセスに対しロックする
      If (Locked([Inventory]))   ` まだロックされいれば
         DELAY PROCESS (Current process;5)   ` 絶え間ないロード指示を避ける
      End if
   Until (Not (Locked([Inventory])))
   [Inventory]Part Qty := [Inventory]Part Qty - 1   ` レコードを更新
   SAVE RECORD ([Inventory])   ` レコードを保存
   UNLOAD RECORD ([Inventory])   ` 他のユーザに対しアンロックする
   READ ONLY([Inventory])

MODIFY RECORDコマンドはレコードがロックされている場合には、自動的にそれをユーザに通知し、レコードが更新されることを防ぎます。以下の例では最初にLocked関数を使用してレコードの状態を調べることで、この自動的な通知を避けています。レコードがロックされている場合には、ユーザが処理を中断できるようにします。

以下の例は、[commands]テーブルのカレントレコードがロックされているかどうかを調べます。ロックされている場合は、プロセスがメソッドによって1秒間延期されます。この技法は、マルチユーザやマルチプロセスの場合両方に用いることができます:

   Repeat
      READ ONLY([Commands]) ` 今は読み書きである必要はない
      QUERY([Commands])
         ` 検索が終了すると、いくつかのレコードが返される
      If ((OK=1) & (Records in selection([Commands])>0))
         READ WRITE([Commands]) ` ーブルを読み書きにする
         LOAD RECORD([Commands])
         While (Locked([Commands]) & (OK=1)) `レコードがロックされいたら
               ` レコードがアンロックされるまでループ
               ` ロックしいるのは誰か?
            LOCKED ATTRIBUTES([Commands];$Process;$User;$Machine;$Name)
            If ($Process=-1) ` レコードは削除済み?
               ALERT("The record has been deleted in the meantime.")
               OK:=0
            Else
               If ($User="") ` シングルユーザモード
                  $User:="you"
               End if
               CONFIRM("The record is already used by "+$User+" in the "+$Name+" Process.")
               If (OK=1) ` If you want to wait for a few seconds
                  DELAY PROCESS(Current process;60) ` 1秒待つ
                  LOAD RECORD([Commands])` レコードのロードを試行
               End if
            End if
         End while
         If (OK=1) ` レコードがアンロックされいる
            MODIFY RECORD([Commands]) ` レコードを更新
            UNLOAD RECORD([Commands])
         End if
         READ ONLY([Commands]) ` 読み込みのみに戻す
         OK:=1
      End if
   Until (OK=0)

マルチユーザまたはマルチプロセス環境でのコマンドの使用


いくつかのコマンドは、レコードがロックされていることを検知した時点で、特定の処理を実行します。これらのコマンドは、レコードがロックされていない場合には、通常どおりの処理を遂行します。

以下に、レコードがロックされていることを検知した場合の各コマンドの処理を示します。

MODIFY RECORD: レコードが使用されていることを示すダイアログボックスを表示します。レコードは表示されず、ユーザはレコードを修正できません。デザインモ−ドでは、レコ−ドは読み込みのみ状態で表示されます。

MODIFY SELECTION: ユーザがレコードをダブルクリックして修正しようとした場合を除いて通常どおりの処理を行います。MODIFY SELECTIONはレコードが使用されていることを示すダイアログボックスを表示し、読み込みのみ状態でレコードのアクセスを許可します。

APPLY TO SELECTION: ロックされたレコードをロードしますが、そのレコードを更新しません。APPLY TO SELECTIONは、特別な処置を行わずにテーブルからレコードを読み取ります。ロックされたレコードを検知すると、コマンドはそのレコードをLockedSetシステムセットに格納します。

DELETE SELECTION: ロックされたレコードを削除せずにスキップします。コマンドはロックされたレコードを見使えると、それをLockedSetシステムセットに格納します。

DELETE RECORD: レコードがロックされている場合、このコマンドは何も行いません。エラーも返しません。このコマンドを実行する前にレコードがアンロックされていることを確認する必要があります。

SAVE RECORD: レコードがロックされている場合、このコマンドは何も行いません。エラーも返しません。このコマンドを実行する前にレコードがアンロックされていることを確認する必要があります。・ARRAY TO SELECTION: ロックされたレコードは保存しません。ロックされたレコードを検知すると、コマンドはそのレコードをLockedSetシステムセットに格納します。

GOTO RECORD: マルチユーザ/マルチプロセスデータベース上では、他のユーザがレコードを削除、または追加することができます。したがって、レコード番号が変更される場合があるため、マルチユーザデータベース上でレコード番号を使用して直接レコードを参照する場合には、十分注意してください。

セット: セットに使用される情報を他のユーザやプロセスが変更する可能性があるため、セットの使用には細心の注意が必要です。

参照

LOAD RECORD, Locked, LOCKED ATTRIBUTES, READ ONLY, Read only state, READ WRITE, UNLOAD RECORD, メソッド, 変数.


4D - Documentation   French   English   German   Spanish   日本語   4D v11 SQLコマンドテーマリスト   4D v11 SQLインデックス   4D v11 SQL定数テーマリスト   戻る   前   次