LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type:
READ [LOCAL]
| [LOW_PRIORITY] WRITE
UNLOCK TABLES
MySQL では、クライアントセッションは、ほかのセッションと連携してテーブルにアクセスするために、またはそのセッションにテーブルへの排他的アクセスが必要な期間中はほかのセッションによってそのテーブルが変更されないようにするために、明示的にテーブルロックを取得できます。セッションがロックを取得または解放できるのは、それ自体のためだけです。あるセッションが別のセッションのためにロックを取得したり、別のセッションによって保持されているロックを解放したりすることはできません。
ロックを使用すると、トランザクションをエミュレートするか、またはテーブル更新時の速度を向上させることができます。これについては、このセクションのあとの方でさらに詳細に説明されています。
LOCK TABLES
は、現在のクライアントセッションのテーブルロックを明示的に取得します。テーブルロックは、ベーステーブルまたはビューに対して取得できます。ロックされる各オブジェクトに対する LOCK TABLES
権限と SELECT
権限が必要です。
ビューのロックの場合、LOCK TABLES
は、そのビューで使用されているすべてのベーステーブルをロックされるテーブルのセットに追加し、それらのテーブルを自動的にロックします。セクション13.3.5.2「LOCK TABLES とトリガー」で説明されているように、LOCK TABLES
によって明示的にテーブルをロックした場合は、トリガーで使用されているテーブルもすべて暗黙的にロックされます。
UNLOCK TABLES
は、現在のセッションによって保持されているテーブルロックをすべて明示的に解放します。LOCK TABLES
は、新しいロックを取得する前に、現在のセッションによって保持されているテーブルロックをすべて暗黙的に解放します。
UNLOCK TABLES
の別の使用法として、すべてのデータベース内のすべてのテーブルをロックできる FLUSH TABLES WITH READ LOCK
ステートメントによって取得されたグローバルな読み取りロックの解放があります。セクション13.7.6.3「FLUSH 構文」を参照してください。(これは、特定時点のスナップショットを取得できる、Veritas などのファイルシステムがある場合にバックアップを取得するための非常に便利な方法です。)
テーブルロックでは、ほかのセッションによる不適切な読み取りまたは書き込みからのみ保護されます。WRITE
ロックを保持しているセッションは、DROP TABLE
や TRUNCATE TABLE
などのテーブルレベルの操作を実行できます。READ
ロックを保持しているセッションの場合、DROP TABLE
および TRUNCATE TABLE
操作は許可されません。TRUNCATE TABLE
操作はトランザクションセーフではないため、セッションがアクティブなトランザクション中または READ
ロックを保持している間にこの操作を行おうとすると、エラーが発生します。
次の説明は、TEMPORARY
以外のテーブルにのみ適用されます。LOCK TABLES
は TEMPORARY
テーブルに対して許可されます (ただし、無視されます)。テーブルは、ほかのどのようなロックが有効になっているかには関係なく、そのテーブルが作成されたセッションから自由にアクセスできます。ほかのどのセッションもそのテーブルを参照できないため、ロックは必要ありません。
LOCK TABLES
の使用に関するその他の条件や、LOCK TABLES
が有効になっている間は使用できないステートメントについては、セクション13.3.5.3「テーブルロックの制限と条件」を参照してください。
ロック取得のルール
現在のセッション内でテーブルロックを取得するには、LOCK TABLES
ステートメントを使用します。次のロックタイプを使用できます。
READ [LOCAL]
ロック:
このロックを保持しているセッションは、テーブルを読み取ることができます (ただし、書き込みはできません)。
複数のセッションが同時にテーブルに対する
READ
ロックを取得できます。ほかのセッションは、
READ
ロックを明示的に取得することなく、テーブルを読み取ることができます。LOCAL
修飾子を使用すると、ロックが保持されている間、ほかのセッションによる競合しないINSERT
ステートメント (並列挿入) を実行できます。(セクション8.10.3「同時挿入」を参照してください。)ただし、ロックを保持している間、サーバーの外部にあるプロセスを使用してデータベースを操作しようとしている場合は、READ LOCAL
を使用できません。InnoDB
テーブルの場合、READ LOCAL
はREAD
と同じです。
[LOW_PRIORITY] WRITE
ロック:
このロックを保持しているセッションは、テーブルの読み取りおよび書き込みが可能です。
このロックを保持しているセッションだけがテーブルにアクセスできます。ロックが解放されるまで、ほかのどのセッションもアクセスできません。
WRITE
ロックが保持されている間、テーブルに対するほかのセッションからのロック要求はブロックされます。LOW_PRIORITY
修飾子は何の効果もありません。以前のバージョンの MySQL では、ロックの動作に影響を与えましたが、これは当てはまらなくなっています。MySQL 5.6.5 の時点では、これは非推奨であり、使用すると警告が生成されます。代わりに、LOW_PRIORITY
のないWRITE
を使用してください。
LOCK TABLES
ステートメントが、いずれかのテーブルに対するほかのセッションによって保持されているロックのために待機する必要がある場合、このステートメントはすべてのロックを取得できるまでブロックされます。
ロックが必要なセッションは、必要なすべてのロックを 1 つの LOCK TABLES
ステートメントで取得する必要があります。このように取得されたロックが保持されている間、このセッションは、ロックされたテーブルにのみアクセスできます。たとえば、次のステートメントシーケンスでは、t2
が LOCK TABLES
ステートメントでロックされていないため、このテーブルにアクセスしようとするとエラーが発生します。
mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
INFORMATION_SCHEMA
データベース内のテーブルは例外です。これらのテーブルは、セッションが LOCK TABLES
によって取得されたテーブルロックを保持している間であっても、明示的にロックされることなくアクセスできます。
ロックされたテーブルを、同じ名前を使用して 1 つのクエリーで複数回参照することはできません。代わりにエイリアスを使用し、そのテーブルと各エイリアスのための個別のロックを取得します。
mysql> LOCK TABLE t WRITE, t AS t1 READ;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;
最初の INSERT
では、ロックされたテーブルに対する同じ名前への参照が 2 つ存在するため、エラーが発生します。2 番目の INSERT
は、テーブルへの参照で異なる名前が使用されるため、成功します。
ステートメントがエイリアスを使用してテーブルを参照する場合は、その同じエイリアスを使用してテーブルをロックする必要があります。エイリアスを指定しないでテーブルをロックすることはできません。
mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
逆に、エイリアスを使用してテーブルをロックする場合は、ステートメント内でそのエイリアスを使用してテーブルを参照する必要があります。
mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;
WRITE
ロックは通常、更新ができるだけ早く処理されるように、READ
ロックより高い優先度を持っています。つまり、あるセッションが READ
ロックを取得したあと、別のセッションが WRITE
ロックを要求した場合は、WRITE
ロックを要求したセッションがロックを取得して解放するまで、以降の READ
ロック要求が待たされます。
LOCK TABLES
は、次のようにロックを取得します。
ロックされるすべてのテーブルを内部で定義された順序でソートします。ユーザーから見て、この順序は定義されていません。
テーブルを読み取りおよび書き込みロックでロックする場合は、書き込みロック要求を読み取りロック要求の前に配置します。
セッションがすべてのロックを取得するまで、1 回につき 1 つのテーブルをロックします。
このポリシーによって、テーブルロックでデッドロックが発生しないことが保証されます。
LOCK TABLES
または UNLOCK TABLES
は、パーティション化されたテーブルに適用された場合、常にテーブル全体をロックまたはロック解除します。これらのステートメントは、パーティションロックプルーニングをサポートしていません。セクション19.6.4「パーティショニングとロック」を参照してください。
ロック解放のルール
セッションによって保持されているテーブルロックが解放される場合は、すべてのテーブルロックが一度に解放されます。セッションは明示的にロックを解放できます。また、特定の状況で、ロックが暗黙的に解放される場合もあります。
セッションは、
UNLOCK TABLES
によって明示的にロックを解放できます。セッションがすでにロックを保持している間にロックを取得するために
LOCK TABLES
ステートメントを発行した場合は、新しいロックが付与される前に、その既存のロックが暗黙的に解放されます。セッションが (たとえば、
START TRANSACTION
で) トランザクションを開始した場合は、暗黙的なUNLOCK TABLES
が実行され、既存のロックが解放されます。(テーブルロックとトランザクションの間の通信の詳細は、セクション13.3.5.1「テーブルロックとトランザクションの通信」を参照してください。)
クライアントセッションの接続が (正常または異常にかかわらず) 終了した場合、サーバーは、そのセッションによって保持されているすべてのテーブルロック (トランザクションおよび非トランザクション) を暗黙的に解放します。そのクライアントが再接続した場合、ロックは有効でなくなります。さらに、クライアントにアクティブなトランザクションがある場合、サーバーは切断時にそのトランザクションをロールバックし、再接続が発生した場合は、自動コミットが有効になった状態で新しいセッションが開始されます。このため、クライアントは自動再接続を無効にすることが必要になる場合があります。自動再接続が有効な場合、再接続が発生してもクライアントには通知されませんが、すべてのテーブルロックまたは現在のトランザクションが失われます。自動再接続が無効になっている場合は、接続が削除されると、発行された次のステートメントに対してエラーが発生します。クライアントはそのエラーを検出し、ロックの再取得やトランザクションの再実行などの適切なアクションを実行できます。セクション23.7.16「自動再接続動作の制御」を参照してください。
ロックされたテーブル上で ALTER TABLE
を使用すると、そのテーブルがロック解除される場合があります。たとえば、2 番目の ALTER TABLE
操作を試みると、エラー「テーブル '
が発生する場合があります。これに対処するには、2 番目の変更の前にテーブルを再度ロックします。セクションB.5.7.1「ALTER TABLE での問題」も参照してください。
tbl_name
' は LOCK TABLES でロックされていません」