LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES
LOCK TABLES
では、現在のスレッドのテーブルがロックされます。UNLOCK
TABLES
では、現在のスレッドが保有しているロックが解除されます。現在のスレッドが別の
LOCK TABLES
を発行したり、サーバへの接続が閉じられると、現在のスレッドがロックしているテーブルのロックはすべて暗黙的に解除されます。
MySQL 4.0.2 で LOCK TABLES
を使用するには、関連するテーブルに対するグローバルな
LOCK TABLES
権限と
SELECT
権限が必要です。MySQL 3.23
では、関連するテーブルに対する
SELECT
、insert
、DELETE
、UPDATE
の各権限が必要です。
LOCK TABLES
を使用する主な理由は、トランザクションをエミュレートしたり、テーブルの更新時に処理を迅速化したりするためです。これについては、詳しく後述します。
あるスレッドがテーブルに対する
READ
ロックを取得すると、そのスレッド(および他のすべてのスレッド)はそのテーブルからの読み取りのみ実行できるようになります。あるスレッドがテーブルに対する
WRITE
ロックを取得すると、ロックを保有しているスレッドだけがそのテーブルからの読み取りやテーブルへの書き込みを実行できるようになります。他のスレッドはブロックされます。
READ LOCAL
と READ
の違いは、READ LOCAL
の場合、ロックの保有中に、コンフクリトを発生させない
INSERT
ステートメントを実行できることです。しかし、ロックの保有中にデータベースを
MySQL
の外部で操作しようとする場合は、この機能を使用できません。
LOCK TABLES
の使用時には、使用するテーブルをすべてロックし、またクエリで使用するエイリアスと同じ名前を使用する必要があります。1
つのクエリで同じテーブルを何度も指定する(エイリアスを使用して)場合は、各エイリアスに対してロックを取得しなければなりません。
更新をできるだけ早く処理するために、WRITE
ロックは、通常、READ
ロックより優先されます。そのため、あるスレッドが
READ
ロックを取得し、別のスレッドが
WRITE
ロックを要求している場合、後続の
READ
ロック要求は、WRITE
スレッドがロックを取得し、その後そのロックを解除するまで待機します。LOW_PRIORITY
WRITE
ロックでは、そのスレッドが
WRITE
ロックを取得する前に、他のスレッドが
READ
ロックを取得することができます。その間、LOW_PRIORITY
WRITE
ロックを発行したスレッドは待機します。LOW_PRIORITY
WRITE
は、READ
ロックを取得しようとするスレッドが皆無になるときがあるとわかっている場合にのみ使用してください。
LOCK TABLES
は次のように機能します。
ロックするテーブルを内部定義された順序(ユーザから見た場合は未定義)でソートする。
読み取りロックと書き込みロックでテーブルがロックされる場合は、読み取りロックより書き込みロックを優先する。
一度に 1 つのテーブルをロックし、スレッドがすべてのロックを取得するまでロック処理を繰り返す。
このポリシーによって、テーブルのロックでデッドロックの発生が回避されます。ただし、このスキーマに関しては注意すべき点が他にもあります。
MySQL でテーブルに対して LOW_PRIORITY
WRITE
ロックを使用した場合、そのスレッドは
READ
ロックを要求する他のスレッドがなくなるまでの間のみ待機し、READ
を要求する他のスレッドがなくなった時点でロックを取得します。そのスレッドで
WRITE
ロックを取得した後に、ロックテーブルリストの次のテーブルのロックを取得しようと待機しているときには、他のスレッドの方がいずれも
WRITE
ロックが解除されるまで待つことになります。これによってアプリケーションで深刻な問題が発生する場合は、一部のテーブルをトランザクションセーフテーブルに変換することを検討してください。
テーブルのロックを取得しようと待機しているスレッドを、安全な方法で強制終了するには、KILL
を使用します。 See 項4.6.7. 「KILL
構文」。
注意: INSERT DELAYED
で使用しているテーブルは、ロックすべきではありません。なぜなら、この場合、INSERT
が独立したスレッドで実行されるためです。
個々の UPDATE
ステートメントでは、いずれも処理が原子的に行われるため、通常、テーブルをロックする必要はありません。現在実行中の
SQL
ステートメントが、他のスレッドによって妨害されることはまったくありません。しかし、次に示すように、テーブルをロックする必要が生じる場合もいくつかあります。
一連のテーブルに対して多くの操作を実行する場合、使用するテーブルをロックした方が処理がはるかに迅速になる。当然ながら、この場合の短所は、READ
ロックされているテーブルについては、どのスレッドも(ロックを保有しているスレッドも含む)このテーブルを更新できなくなり、WRITE
ロックされているテーブルについては、ロックを保有しているスレッド以外、どのスレッドもこのテーブルを読み取れなくなることである。
LOCK TABLES
の使用時にいくつかの面で処理が迅速になる理由は、MySQL
でキーのキャッシュが UNLOCK
TABLES
が呼び出されるまでフラッシュされないためである(通常、キーのキャッシュは各
SQL
ステートメントの後にフラッシュされる)。それによって、MyISAM
テーブルに対する挿入、更新、削除処理が迅速化される。
トランザクションをサポートしていないストレージエンジンを
MySQL
で使用している場合、SELECT
と
UPDATE
の間に他のスレッドに割り込まれないようにするには、LOCK
TABLES
を使用する必要がある。次の例では、安全に処理を実行するために
LOCK TABLES
を発行する必要がある。
mysql>LOCK TABLES trans READ, customer WRITE;
mysql>SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql>UPDATE customer SET total_value=sum_from_previous_statement
->WHERE customer_id=some_id;
mysql>UNLOCK TABLES;
LOCK TABLES
を発行しないと、SELECT
ステートメントと UPDATE
ステートメントの実行の間に別のスレッドが
trans
テーブルに新しいレコードを挿入してしまう可能性がある。
多くの場合、自身の加算を行う更新(UPDATE
customer SET value=value+new_value
)や
LAST_INSERT_ID()
関数の使用により、LOCK TABLES
の使用を避けることができます。
また、ユーザレベルのロック関数
GET_LOCK()
と
RELEASE_LOCK()
を使用して問題を解決できる場合もあります。これらのロックはサーバのハッシュテーブルに保存され、高速にするため
pthread_mutex_lock()
と
pthread_mutex_unlock()
で実装されます。 See
項6.3.6.2. 「その他の各種関数」。
ロックポリシーの詳細については、項5.3.1. 「MySQL のテーブルロック方法」 を参照してください。
全データベースの全テーブルを読み取りロックでロックするには、FLUSH
TABLES WITH READ LOCK
コマンドを使用します。See
項4.6.4. 「FLUSH
構文」。特定の時点のスナップショットを取ることができる、Veritas
などのファイルシステムを使用している場合には、このコマンドがバックアップを作成するときに非常に役立ちます。
注意: LOCK
TABLES
はトランザクションセーフではありません。アクティブなトランザクションは、テーブルロックの試行前に暗黙的にコミットされます。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.