4Dと4D Serverは、マルチユーザまたはマルチプロセスのコンフリクトを防ぐことによってマルチユーザデータベースを自動的に管理します。2人のユーザまたは2つのプロセスが、同時に同じレコードやオブジェクトを修正することはできませんが、2番目のユーザやプロセスはレコードやオブジェクトに読み込みのみのアクセスを得ることができます。
この章のマルチユーザコマンドを使用しなければならない状況がいくつかあります:
- プログラミング言語を使用してレコードを更新する。
- マルチユーザ環境でカスタムユーザインタフェースを使用する。
- トランザクション内で関連する変更を保存する。
マルチプロセスデータベースでコマンドを使用するときに注意すべき重要な概念が3つあります:
- 各テーブルは、読み込み専用または読み書き可能のどちらかに設定される。
- レコードは、ロードされた時点で他のプロセスに対しロック状態となり、アンロ-ドされた時点でロック解除になる。
- ロックされたレコードは、更新することはできない。
この章では、マルチユーザデータベースで作業を実行する人をローカルユーザと呼びます。マルチユーザデータベースを使用する他の人を他のユーザと呼びます。この節では、ローカルユーザの観点で説明します。またマルチプロセスの観点から、データベース上で処理を実行しているプロセスをカレントプロセスと呼びます。その他の実行中のプロセスは他のプロセスと呼びます。この章では、カレントプロセスの観点で説明します。
ローカルユーザやカレントプロセスは、ロックされたレコードを更新できません。ロックされたレコードをロードすることは可能ですが、更新することはできません。他のユーザやプロセスが更新するためにレコードをロードした時点またはスタックした時点で、そのレコードはロックされます。レコードを更新しているユーザだけが、そのレコードをロックされていない状態で取り扱うことができます。その他のすべてのユーザやプロセスは、レコードがロック状態になるため更新することはできません。ロックされていない状態でレコードをロードするには、テーブルを必ず読み書き状態に設定しなければなりません。
データベース中の各テーブルは、データベースの各ユーザおよび各プロセスに対して読み込みのみ状態と読み書き状態のいずれかになっています。読み込みのみとは、テーブルからレコードをロードすることはできるが更新することはできないという状態です。読み書きとは、テーブルのレコードをロード可能であり、他のユーザが先にそのレコードをロックしていない場合には更新することができる状態です。
テーブルの状態を変更すると、その変更は次からロードされるレコードに影響を及ぼすことに注意してください。テーブル状態を変更する際に既にロードされていたレコードは、状態変更によって影響を受けることはありません。
テーブルが読み込みのみ状態に設定されると、ロードしたレコードは常に更新不可にされます。つまり、レコードの表示と印刷を実行することはできますが、更新することはできません。
この読み込みのみ状態は、既存レコードの更新処理に対してのみ適用されることに注目してください。読み込みのみ状態は新規レコードの作成に影響を与えません。デザインモードのメニューやCREATE RECORD、ADD RECORDを使って読み込みのみテーブルにレコードを追加することができます。ARRAY TO SELECTION コマンドは、レコードの作成と更新と両方が可能なので読み込みのみ状態に影響されないという点に注意して下さい。
4Dは、レコードに対する書き込み動作を必要としないコマンド利用時、テーブルを自動的に読み込みのみ状態にします。以下そのコマンドを示します:
テーブルの現在の状態を知るには、Read only state ファンクションを使用します。
これらのコマンドを実行する前に、4Dはカレントプロセスにおけるテーブルのそのときの状態 (読み込みのみまたは読み書き) を保持します。コマンドを実行した後でテーブルの状態を元に戻します。
読み書き状態のテーブルからロードされたレコードは、他のユーザがそのレコードを先にロックしていなければ更新可能になります。レコードが他のユーザによってロックされている場合にはレコードをロックされたレコードとしてロードできますが、更新はできません。
テーブルが読み書き状態に設定され、ロードしたレコードがロックされていない時に、レコードの更新が可能になります。
あるユーザが読み書き状態のテーブルからレコードをロードすると、他のユーザはレコードをロードできますが、更新することはできません。しかし他のユーザはデザインモード内での手動によるレコード追加、あるいはCREATE RECORDやADD 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コマンドを使用すると、レコードをロックしているユーザやプロセスを知ることができます。
以下の例は、アンロックされたレコードをロードするための最も単純なループ処理を示しています:
このループ処理は、レコードがロック解除されるまで繰り返されます。
このようなループ処理は、ユーザがループが終了するまで待たされるため、レコードが他のユーザにロックされる可能性がほとんどない場合にのみ使用することができます。したがって、メソッドからのみレコードを更新するような場合以外では使用することはできません。
以下の例は先のループを使用してアンロックされたレコードをロードし、更新を行っています:
MODIFY RECORDコマンドはレコードがロックされている場合には、自動的にそれをユーザに通知し、レコードが更新されることを防ぎます。以下の例では最初にLocked関数を使用してレコードの状態を調べることで、この自動的な通知を避けています。レコードがロックされている場合には、ユーザが処理を中断できるようにします。
以下の例は、[commands]テーブルのカレントレコードがロックされているかどうかを調べます。ロックされている場合は、プロセスがメソッドによって1秒間延期されます。この技法は、マルチユーザやマルチプロセスの場合両方に用いることができます:
いくつかのコマンドは、レコードがロックされていることを検知した時点で、特定の処理を実行します。これらのコマンドは、レコードがロックされていない場合には、通常どおりの処理を遂行します。
以下に、レコードがロックされていることを検知した場合の各コマンドの処理を示します。
- 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: マルチユーザ/マルチプロセスデータベース上では、他のユーザがレコードを削除、または追加することができます。したがって、レコード番号が変更される場 合があるため、マルチユーザデータベース上でレコード番号を使用して直接レコードを参照する場合には、十分注意してください。
- : セットに使用される情報を他のユーザやプロセスが変更する可能性があるため、セットの使用には細心の注意が必要です。