このセクションでは、ユーザーレベルロックの操作に使用される関数について説明します。
表 12.19 「ロック関数」
名前 | 説明 |
---|---|
GET_LOCK() |
名前付きロックを取得します |
IS_FREE_LOCK() |
名前付きロックが解放されているかどうか |
IS_USED_LOCK() |
指定されたロックが使用中かどうか。true の場合は接続識別子を返します |
RELEASE_ALL_LOCKS() |
現在の名前付きロックをすべて解放 |
RELEASE_LOCK() |
指定したロックを解放 |
-
GET_LOCK(
str
,timeout
)timeout
秒のタイムアウトを使用して、文字列str
で指定された名前でロックの取得を試みます。 負のtimeout
値は、無限のタイムアウトを表します。 ロックは排他的です。 あるセッションで保持されている間は、他のセッションは同じ名前のロックを取得できません。ロックの取得に成功した場合は
1
を返し、試行がタイムアウトになった場合 (たとえば、ほかのクライアントがすでにその名前をロックしている場合) は0
を返し、エラー (メモリー不足や mysqladmin kill によるスレッドの停止など) が発生した場合はNULL
を返します。GET_LOCK()
で取得されたロックは、RELEASE_LOCK()
を実行して明示的に解放されるか、セッションの終了時に暗黙的に解放されます (通常または異常)。GET_LOCK()
で取得されたロックは、トランザクションのコミットまたはロールバック時に解放されません。GET_LOCK()
は、メタデータロック (MDL) サブシステムを使用して実装されます。 複数の同時ロックを取得でき、GET_LOCK()
は既存のロックを解放しません。 たとえば、次のステートメントを実行するとします:SELECT GET_LOCK('lock1',10); SELECT GET_LOCK('lock2',10); SELECT RELEASE_LOCK('lock2'); SELECT RELEASE_LOCK('lock1');
2 つ目の
GET_LOCK()
は 2 つ目のロックを取得し、両方のRELEASE_LOCK()
コールは 1 (成功) を返します。特定のセッションで同じ名前の複数のロックを取得することもできます。 他のセッションは、取得しているセッションがその名前のロックをすべて解放するまで、その名前のロックを取得できません。
GET_LOCK()
で取得された一意の名前付きロックは、パフォーマンススキーマのmetadata_locks
テーブルに表示されます。OBJECT_TYPE
カラムにはUSER LEVEL LOCK
と示され、OBJECT_NAME
カラムにはロック名が示されます。 same 名に対して複数のロックが取得された場合、その名前の最初のロックのみがmetadata_locks
テーブルの行を登録します。 名前の後続のロックでは、ロック内のカウンタが増分されますが、追加のメタデータロックは取得されません。 名前の最後のロックインスタンスが解放されると、ロックのmetadata_locks
行が削除されます。複数のロックを取得する機能は、クライアント間でデッドロックが発生する可能性があることを意味します。 これが発生すると、サーバーは呼出し側を選択し、そのロック取得リクエストを
ER_USER_LOCK_DEADLOCK
エラーで終了します。 このエラーによってトランザクションがロールバックされることはありません。MySQL では、64 文字のロック名に最大長が適用されます。
GET_LOCK()
を使用すると、アプリケーションロックを実装したり、レコードロックのシミュレーションを行なったりできます。 名前はサーバー全体にわたってロックされます。 1 つのセッション内で名前がロックされた場合は、GET_LOCK()
によって、別のセッションによる同じ名前を持つロックのリクエストがブロックされます。 これにより、指定されたロック名について合意したクライアントは、その名前を使用すると共同のアドバイザリロックを実行できます。 ただし、共同するクライアントのセットに属さないクライアントも、不注意と故意のどちらででも、名前をロックできることに注意してください。したがって、共同するクライアントがその名前をロックできないようにしてください。 この可能性を減らす方法の 1 つは、データベース固有またはアプリケーション固有のロック名を使用することです。 たとえば、db_name.str
またはapp_name.str
形式のロック名を使用します。複数のクライアントがロックを待機している場合、それらがロックを取得する順序は定義されていません。 アプリケーションでは、クライアントがロックリクエストを発行した順序と同じ順序でロックを取得することを想定しないでください。
GET_LOCK()
は、ステートメントベースのレプリケーションでは安全ではありません。binlog_format
がSTATEMENT
に設定されているときに、この関数を使用すると、警告のログが記録されます。注意複数の名前付きロックを取得する機能を使用すると、単一のステートメントで多数のロックを取得できます。 例:
INSERT INTO ... SELECT GET_LOCK(t1.col_name) FROM t1;
これらのタイプのステートメントには、特定の悪影響がある場合があります。 たとえば、ステートメントが途中で失敗してロールバックされた場合、障害ポイントまで取得されたロックは引き続き存在します。 目的が、挿入された行と取得されたロックの間に対応するものである場合、その目的は満たされません。 また、ロックが特定の順序で付与されることが重要な場合は、オプティマイザが選択する実行計画によって結果セットの順序が異なる可能性があることに注意してください。 このような理由から、アプリケーションをステートメントごとに単一のロック取得コールに制限することをお薦めします。
プラグインサービスまたは一連のユーザー定義関数として、別のロックインタフェースを使用できます。 このインタフェースは、
GET_LOCK()
および関連する関数によって提供されるインタフェースとは異なり、ロック名前空間と個別の読み取り/書き込みロックを提供します。 詳細は、セクション5.6.8.1「ロックサービス」を参照してください。 -
IS_FREE_LOCK(
str
)str
という名前が付けられたロックが使用可能であるか (つまり、ロックされていないか) どうかをチェックします。 ロックが使用可能である (だれもロックを使用していない) 場合は1
を返し、使用中である場合は0
を返し、エラー (不正な引数など) が発生した場合はNULL
を返します。この関数は、ステートメントベースのレプリケーションでは安全に使用できません。
binlog_format
がSTATEMENT
に設定されているときに、この関数を使用すると、警告のログが記録されます。 -
IS_USED_LOCK(
str
)str
という名前が付けられたロックが使用中であるか (つまり、ロックされているか) どうかをチェックします。 その場合は、ロックを保持するクライアントセッションの接続識別子を返します。 そうでない場合は、NULL
を返します。この関数は、ステートメントベースのレプリケーションでは安全に使用できません。
binlog_format
がSTATEMENT
に設定されているときに、この関数を使用すると、警告のログが記録されます。 -
RELEASE_ALL_LOCKS()
現在のセッションで保持されているすべての名前付きロックを解放し、解放されたロックの数を返します (存在しなかった場合は 0)
この関数は、ステートメントベースのレプリケーションでは安全に使用できません。
binlog_format
がSTATEMENT
に設定されているときに、この関数を使用すると、警告のログが記録されます。 -
RELEASE_LOCK(
str
)GET_LOCK()
を使用して取得された文字列str
によって名前が付けられたロックを解除します。 ロックが解除された場合は1
を返し、このスレッドによってロックが確立されなかった場合 (その場合、ロックは解除されません) は0
を返し、名前付きのロックが存在しない場合はNULL
を返します。GET_LOCK()
を呼び出しても取得されなかった場合や、事前に解除された場合は、ロックが存在しません。DO
ステートメントは、RELEASE_LOCK()
とともに使用すると便利です。 セクション13.2.3「DO ステートメント」を参照してください。この関数は、ステートメントベースのレプリケーションでは安全に使用できません。
binlog_format
がSTATEMENT
に設定されているときに、この関数を使用すると、警告のログが記録されます。