Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

LOCK

テーブルをロックします。

Synopsis

LOCK [TABLE] tablename IN EXCLUSIVE MODE [WAIT seconds]
LOCK [TABLE] tablename IN SHARE MODE [WAIT seconds]

引数

tablename ロック対象のテーブルの名前。tablename は既存のテーブルである必要があります。
IN EXCLUSIVE MODE と IN SHARE MODE キーワード句 IN EXCLUSIVE MODE は、通常の Caché ロックを作成します。キーワード句 IN SHARE MODE は、共有 Caché ロックを作成します。
seconds オプション — ロック取得の試行期間を指定する秒数。この秒数を経過するとタイムアウトになります。省略した場合、既定のタイムアウトが適用されます。

説明

LOCKLOCK TABLE は同義語です。

LOCK コマンドは、SQL テーブルを明示的にロックします。このテーブルは、ユーザが適切な特権を持つ既存のテーブルである必要があります。tablename が実在しないテーブルである場合、コンパイル・エラーが発生して LOCK が失敗します。tablename が一時テーブルである場合、コマンドは正常に完了しますが、処理は何も実行されません。tablename がビューである場合、SQLCODE -400 エラーが発生してコマンドが失敗します。

UNLOCK コマンドは LOCK 操作を取り消します。明示的な LOCK コマンドは、同じモードで UNLOCK を明示的に発行するまで、またはプロセスが終了するまで有効です。

LOCK を使用してテーブルを複数回ロックすることができますが、明示的にロックした回数と同じ回数だけ明示的に UNLOCK を適用する必要があります。UNLOCK のたびに、対応する LOCK と同じモードを指定する必要があります。

特権

LOCK コマンドは特権を必要とする操作です。LOCK IN SHARE MODE を使用する前に、指定されたテーブルに対する SELECT 特権をプロセスに付与しておく必要があります。LOCK IN EXCLUSIVE MODE を使用する前に、指定されたテーブルに対する INSERT、UPDATE、および DELETE 特権をプロセスに付与しておく必要があります。IN EXCLUSIVE MODE では、テーブルの 1 つ以上のフィールドに対する INSERT、または UPDATE 特権が必要です。特権がない場合は、SQLCODE -99 エラー (特権違反) が返されます。%CHECKPRIV コマンドを呼び出すことにより、現在のユーザが必要な特権を持っているかどうかを確認できます。$SYSTEM.SQL.CheckPriv()Opens in a new tab メソッドを呼び出すことにより、指定のユーザが必要な特権を持っているかどうかを確認できます。特権の割り当てについては、"GRANT" コマンドを参照してください。

これらの特権はロック取得に必要なもので、ロックの性質を定義するものではありません。IN EXCLUSIVE MODE ロックは、ロック保有者に対応する特権があるかどうかにかかわらず、他のプロセスから INSERT、UPDATE、および DELETE の操作が実行できないようにします。

ロック・モード

LOCK では、SHARE と EXCLUSIVE の 2 つのモードがサポートされます。これらのロック・モードに相互依存性はありません。SHARE ロックと EXCLUSIVE ロックの両方を同一のテーブルに適用できます。EXCLUSIVE モードのロックは、EXCLUSIVE モードの UNLOCK でのみアンロックできます。SHARE モードのロックは、SHARE モードの UNLOCK でのみアンロックできます。

  • LOCK mytable IN SHARE MODE では、他のプロセスから mytable に対する EXCLUSIVE ロックの発行、DROP TABLE などの DDL 操作の呼び出しを実行できません。

  • LOCK mytable IN EXCLUSIVE MODE では、他のプロセスから mytable に対する EXCLUSIVE ロックや SHARE ロックの発行や、挿入、更新、削除操作の実行、DROP TABLE などの DDL 操作の呼び出しを実行できません。

LOCK では、テーブルに対する読み取りアクセスが許可されます。他のプロセスからの、READ UNCOMMITTED モード (既定は SELECT モード) にあるテーブルの SELECT の実行は、どの LOCK モードでも阻止されません。

ロックの競合

  • 別のユーザが IN EXCLUSIVE MODE でテーブルを既にロックしている場合、どのロック・モードも適用できません。

  • 別のユーザが IN SHARE MODE でテーブルを既にロックしている場合、IN SHARE MODE でテーブルにさらにロックを適用することはできますが、IN EXCLUSIVE MODE のロックは適用できません。

このような LOCK 競合がある場合、SQLCODE -110 エラーが生成され、%msg "テーブル 'Sample.Person' の共有レベルのロックを獲得できません" が生成されます。

ロック・タイムアウト

LOCK は、タイムアウトが発生するまで、指定された SQL テーブル・ロックの獲得を試行します。タイムアウトが発生すると、LOCK は SQLCODE -110 エラーを生成します。

  • WAIT seconds を指定している場合、その秒数が経過すると SQL テーブル・ロック・タイムアウトが発生します。

  • 指定していない場合、SQL テーブル・ロック・タイムアウトは、現在のプロセスの SQL タイムアウトが経過すると発生します。現在のプロセスのロック・タイムアウトは、ProcessLockTimeout メソッド SetProcessLockTimeout() および GetProcessLockTimeout() を使用して設定できます。SQL コマンド SET OPTION に LOCK_TIMEOUT オプションを指定して、現在のプロセスにロック・タイムアウトを設定することもできます。(SET OPTION は SQL シェルからは使用できません。)現在のプロセスの SQL ロック・タイムアウトは、既定で、システム全体に適用される SQL ロック・タイムアウトになります。

  • 指定していない場合、SQL テーブル・ロック・タイムアウトは、システム全体の SQL タイムアウトが経過すると発生します。このシステム全体の既定は、10 秒です。システム全体のロック・タイムアウトは、以下の 2 つの方法で設定できます。

    • SetLockTimeout() メソッドを使用します。これは新規のプロセスに適用される、システム全体のロック・タイムアウトの既定を即時に変更します。さらに、現在のプロセスに適用される ProcessLockTimeout をこの新しいシステム全体の値に再設定します。システム全体のロック・タイムアウトを設定しても、現在実行中の他のプロセスの ProcessLockTimeout 設定には影響しません。

    • 管理ポータルを使用し、システム, 構成, 一般SQL設定 を選択します。[Lock Timeout (in seconds)] の現在の設定を表示して編集します。これは、構成変更を保存した後に開始する新規のプロセスに適用される、システム全体のロック・タイムアウトの既定を変更します。現在実行中のプロセスには影響しません。

SetLockTimeout()Opens in a new tab メソッドは、値を設定し、直前の値を返します。GetLockTimeout() を使用して、現在のシステム全体のロック・タイムアウト値を返すことができます。

GetSysTimeout
   DO $SYSTEM.SQL.SetLockTimeout()
   SET oldval=$SYSTEM.SQL.GetLockTimeout()
   WRITE oldval," seconds initial system-wide lock setting",!
SetSysTimeout
   DO $SYSTEM.SQL.SetLockTimeout(30,.oldval2)
   WRITE "system-wide lock timeout changed from ",oldval2," to "
   WRITE $SYSTEM.SQL.GetLockTimeout(),!
ResetSysTimeout
   DO $SYSTEM.SQL.SetLockTimeout(oldval,.oldval3)
   WRITE "system-wide lock timeout reset from ",oldval3," to "
   WRITE $SYSTEM.SQL.GetLockTimeout()

SetProcessLockTimeout()Opens in a new tab メソッドは、値を設定し、ステータス・コードを返します。GetProcessLockTimeout() を使用して、現在のプロセスのロック・タイムアウト値を返すことができます。

GetTimeoutDefaults
   SET sysinit=$SYSTEM.SQL.GetLockTimeout()
   WRITE sysinit," initial system-wide lock seconds",!
   SET procinit=$SYSTEM.SQL.GetProcessLockTimeout()
   WRITE procinit," initial process lock seconds",!
SetProcessTimeout
  DO $SYSTEM.SQL.SetProcessLockTimeout(50,.stat)
    IF stat {WRITE $SYSTEM.SQL.GetProcessLockTimeout()," set process lock seconds",! }
SetProcessTimeoutAgain
  DO $SYSTEM.SQL.SetProcessLockTimeout(60,.stat2)
    IF stat2 {WRITE $SYSTEM.SQL.GetProcessLockTimeout()," set process lock seconds",! }
SetProcessTimeoutMinimal
  DO $SYSTEM.SQL.SetProcessLockTimeout()
  WRITE $SYSTEM.SQL.GetProcessLockTimeout()," minimal process lock seconds",!
ResetToDefault
  DO $SYSTEM.SQL.SetProcessLockTimeout(procinit)
  WRITE $SYSTEM.SQL.GetProcessLockTimeout()," reset process lock seconds",!

トランザクション処理

LOCK 操作は、トランザクションの構成部分ではありません。LOCK が発行されたトランザクションをロール・バックしてもアンロックされません。UNLOCK は、現在のトランザクションの最後に、または即時に発生するように定義できます。

その他のロック操作

ALTER TABLEDELETE TABLE などの DDL 操作の多くは、排他的なテーブル・ロックを取得します。

INSERTUPDATE、および DELETE コマンドもロックを実行します。既定では、現在のトランザクションの実行中にレコード・レベルでロックが適用されます。これらのコマンドのいずれかが十分な数の (既定の設定では 1000 個) レコードをロックした場合、このロックは自動的にテーブル・ロックに昇格します。LOCK コマンドを使用すると、テーブル・レベルのロックを明示的に設定できるため、データ・リソースのロック制御能力が向上します。キーワード %NOLOCK を指定すると、INSERTUPDATE、および DELETELOCK をオーバーライドできます。

LOCK_TIMEOUT オプションが指定された Caché SQL SET OPTION は、INSERTUPDATEDELETE、または SELECT 操作の現在のプロセスに対してタイムアウトを設定します。

Caché SQL は、SetCachedQueryLockTimeout()Opens in a new tab メソッドをサポートします。“Caché SQL 最適化ガイド” の “クエリ・キャッシュ” を参照してください。

以下の埋め込み SQL 例は、テーブルを作成してロックします。

  ZNSPACE "Samples"
  NEW SQLCODE,%msg
  &sql(CREATE TABLE mytest (
      ID NUMBER(12,0) NOT NULL,
      CREATE_DATE DATE DEFAULT CURRENT_TIMESTAMP(2),
      WORK_START DATE DEFAULT SYSDATE) )
  IF SQLCODE=0 { WRITE "Table created",! }
  ELSEIF SQLCODE=-201 { WRITE "Table already exists",! }
  ELSE { WRITE "CREATE TABLE error: ",SQLCODE
         QUIT }
  ZNSPACE "Samples"
  NEW SQLCODE,%msg
  SET x=$ZHOROLOG
  &sql(LOCK mytest IN EXCLUSIVE MODE WAIT 4) 
  IF SQLCODE=0 { WRITE !,"Table locked" }
  ELSEIF SQLCODE=-110 { WRITE "waited ",$ZHOROLOG-x," seconds"
         WRITE !,"Table is locked by another process",!,%msg }
  ELSE { WRITE !,"Unexpected LOCK error: ",SQLCODE,!,%msg }

ドキュメント、または管理ポータルから SQL プログラムが実行され、プログラムの実行後に直ちに終了するプロセスが生成されます。このように、ロックはほとんど即座に解除されます。このため、ロックの競合を監視するには、まず、Samples ネームスペースで SQL シェルを実行しているターミナルから LOCK mytest IN EXCLUSIVE MODE コマンドを発行します。次に上の埋め込み SQL ロック・プログラムを実行します。ターミナル SQL シェルから UNLOCK mytest IN EXCLUSIVE MODE を発行します。次に上の埋め込み SQL ロック・プログラムを再実行します。

関連項目

FeedbackOpens in a new tab