これは InterSystems FAQ サイトの記事です。
InterSystems製品では、複数のプロセスが同時に同じデータにアクセスする場合、排他制御を行うためにロックを使用できます。
ロックは、データの更新を正しく行い整合性を保つための仕組みで、あるデータに対する更新処理を制御するために使用します。
ロックを操作するには、LOCK(L)というコマンドが使用できます。
こちらの記事では、InterSystems製品で使用できるロックの種類、LOCKコマンドの使い方をご紹介します。
★ロックの種類
増分 | 単純 | |
排他(既定) | LOCK +^A | LOCK ^A |
共有 | LOCK +^A#"S" | LOCK ^A#"S" |
プラス記号 (+) をつけると、増分ロックになります。1つのプロセスで複数の増分ロックを追加できます。
プラス記号 (+) をつけないと、単純ロックになります。こちらは、1つのプロセスで1つのロックのみ所有できます。単純ロックコマンド実行時に既存のロックがあった場合、そのプロセスが保持している既存のロックをすべて削除し、新しいロックを追加します。
排他ロック:
データを更新するために使用するロックです。
プロセスが特定のロック名の付いた排他ロックを所有している時、その他のプロセスは、そのロック名の付いたロックを取得できません。
SQLでいうと、INSERT, UPDATEやDELETE文の実行時にかかります。
共有ロック:
データを参照していることを示すためのロックです。
プロセスが特定のロック名の付いた共有ロックを所有しているときに、その他のプロセスは、そのロック名の付いた共有ロックを取得できます。ただし、その他のプロセスはそのロック名の付いた排他ロックを取得できません。
SQLでいうと、Read Committed モードでの SELECT文の実行時にかかります。
★ロックの方法
ロックを追加する(lockname:ロック名※、locktype:後述)
※ロック名は任意の名前ですが、共通の規則としてロックする項目(グローバル・変数等)の名前と同じロック名を使用します。
LOCK +lockname#locktype
ロックを削除(解放)する
LOCK -lockname#locktype
使用例:
(A) Lock ^a // このコマンドを実行すると、^bだけが最終的に残ります
Lock ^b // ※Lock ^b だけの場合、ほかのロックを全て解放した後、^bだけロックを持ちます
(B) Lock +^a // このコマンドを実行すると、^a,^bの二つロックが残ります。
Lock +^b
尚、正常に終了したプロセスは取得していたロックを全て解放します。
★ロックタイプ(locktype)
S — 共有ロックを追加します。"排他ロックと共有ロック" を参照してください。
E — エスカレートロックを追加します。"非エスカレート・ロックとエスカレート・ロック" を参照してください(後述)。
I — 即時アンロックタイプでロック解除を行います。
D — 遅延アンロックタイプでロック解除を行います。
※エスカレートロック
大量のロックを管理するためにエスカレートロックを使用します。
これは配列のノードをロックする場合に使用されます。例えば、同じ添え字レベルで複数のノードをロックする場合です。
ロックのエスカレーションの例(テーブルロック)
こちらの記事 でテーブルロックの例を紹介しておりますので、参考になさってください。
★ロック管理ユーティリティでできること
次のユーティリティでロックの管理が行えます。
1. 管理ポータルを使用する方法 ⇒ 管理ポータル:システムオペレーション > ロック > ロックを表示(または管理) 2. ^LOCKTAB ユーティリティ を使用する方法 ⇒ %SYS>do ^LOCKTAB 3. プログラムを使用する方法 ⇒ プログラム内でロック情報を取得する方法
これらのユーティリティでは、主にロックの参照・解放(削除)が行えます。
ロックテーブルの参照方法については、関連トピック ロックテーブルの参照方法とその見方 をご覧ください。
以下にそれぞれのユーティリティを使用した、ロックの削除方法をご紹介します。
☆ロックの削除手順(1の管理ポータルで行う方法)
管理ポータル:システムオペレーション > ロック > ロックを管理
→ 該当ロックの「削除」リンクより削除を行います。
☆ロックの削除手順(2の ^LOCKTAB ユーティリティで行う場合)
%SYS>do ^LOCKTAB
:
Node Name: XXX
LOCK table entries at 05:22PM 03/06/2025
308464608 bytes usable, 308472544 bytes available.
Entry Process X# S# Flg W# Item Locked
1) 39740 1 ^["^^c:\intersystems\iris\mgr\"]ISC.LMFMON("License Monitor")
:
8) 30100 1 1 ^["^^c:\intersystems\iris\mgr\user\"]A
Waiters: 25164(XE)
Command=> D // 削除の時は D を入力
Entry to delete: 8 // 削除したいロックの番号を入力 + <Enter>
8) 30100 1 ^["^^c:\intersystems\iris\mgr\user\"]A
Are you sure you want to delete this lock? No => yes // Y(y) を入力+<Enter> でロックが削除される
Entry to delete: // 以下、Q + <Enter> で抜ける
:
☆ロックの削除手順(3のプログラムで行う場合)
// プロセスID=2004 が所有するすべてのロックを削除する
Set rc=##Class(SYS.Lock).DeleteAllLocks(2004)
// リモートクライアントシステム 'SystemA' が所有するすべてのロックを削除する
Set rc=##Class(SYS.Lock).DeleteAllLocks("CSystemA")
/// ロック名やプロセスを指定して削除する
// ^|"^^c:\intersystemsdb\mgr\user"|a(1) ロックを削除する
Set rc=##Class(SYS.Lock).DeleteOneLock("^|""^^c:\intersystemsdb\mgr\user""|a(1)")
// プロセスID=2004 が所有する ^|"^^c:\InterSystemsdb\mgr\user"|a(1) ロックを削除する
Set rc=##Class(SYS.Lock).DeleteOneLock("^|""^^c:\intersystemsdb\mgr\user""|a(1)",2004)
★ロックテーブル サイズの変更
以下メニューからロックテーブルのサイズを変更できます。
管理ポータル:
[システム管理] > [構成] > [追加の設定] > [メモリ詳細設定] → locksiz
※バージョン2023.1以降では、デフォルト値は0でシステムに最適な値が割り当てられます。
この場合、gmheap パラメータで指定された共有メモリサイズのみでこのサイズが制限されます。
※ロックテーブルサイズを変更する場合は、gmheapサイズもあわせて変更します。
※ロックテーブルが一杯になるとコンソールログに、以下のようなエラーメッセージが表示されます。
02/08/25-00:05:09:248 (20093) 2 [Generic.Event] LOCK TABLE FULL!!! (Repeat messages will be suppressed for 20 minutes).
ロックコマンド自体はエラーにはならず待ち状態になります(^LOCKTABには表示されません)。
【ご参考】
適正なロックテーブルサイズの算出方法
ロックテーブルの使用状況を簡単に確認する方法
SQLのUPDATEやDELETEで、ある程度の数のレコードを一括更新するとSQLエラー -110 が発生します。
SQLでレコードをSelectするとSQLエラー -114 が発生します
現在の一般メモリヒープ(gmheap)と取得可能なロックテーブル(locksiz)最大サイズについて
ロックテーブルの参照方法とその見方