Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.2Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  ...  /  メタデータのロック

8.10.4 メタデータのロック

MySQL はメタデータのロックを使用して、オブジェクト (テーブル、トリガーなど) へのアクセスを管理します。メタデータのロックは、データの一貫性を確保するために使用されますが、いくらかのオーバーヘッドがあり、クエリーボリュームが増えるとそれも大きくなります。複数のクエリーが同じオブジェクトにアクセスを試みることが多くなるほど、メタデータの競合が増加します。

メタデータのロックは、テーブル定義キャッシュの代替ではなく、その相互排他ロックとロックは、LOCK_open 相互排他ロックと異なります。次の説明では、メタデータのロックの仕組みに関する情報を提供します。

トランザクションのシリアライザビリティーを確保するため、サーバーは、別のセッションで、未完了の明示的または暗黙的に開始されたトランザクションで使用されているテーブルに対して、セッションがデータ定義言語 (DDL) ステートメントを実行することを許可してはいけません。サーバーは、トランザクション内で使用されているテーブルに対してメタデータロックを獲得し、トランザクションが終了するまでそれらのロックの解放を延期させることによって、これを実現します。テーブルへのメタデータロックは、テーブルの構造への変更を妨げます。このロックアプローチには、あるセッション内のトランザクションによって使用されているテーブルは、トランザクションが終了するまで、ほかのセッションによって DDL ステートメントで使用できないという問題があります。

この原則は、トランザクションテーブルだけでなく、非トランザクションテーブルにも適用されます。あるセッションがトランザクションテーブル t と非トランザクションテーブル nt を次のように使用するトランザクションを開始するとします。

START TRANSACTION;
SELECT * FROM t;
SELECT * FROM nt;

サーバーはトランザクションが終了するまで、tnt の両方に対するメタデータロックを保持します。別のセッションがいずれかのテーブルに対して、DDL または書き込みロック操作を試みると、それはトランザクションの終了時にメタデータロックが解放されるまでブロックされます。たとえば、2 つめのセッションはこれらのいずれかの操作を試みるとブロックされます。

DROP TABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;

サーバーが構文上有効であるが、実行中に失敗するステートメントのメタデータロックを獲得した場合、そのロックを早期に解放しません。失敗したステートメントがバイナリログに書き込まれ、ロックによってログの一貫性が保護されるため、ロックの解放はまだトランザクションの終了まで延期されます。

自動コミットモードでは、各ステートメントが事実上完全なトランザクションであるため、そのステートメントに対して獲得されたメタデータロックは、ステートメントの終了までしか保持されません。

PREPARE ステートメント中に獲得されたメタデータロックは、準備が複数ステートメントトランザクション内で行われる場合でも、ステートメントが準備されると解放されます。

MySQL 5.5 より前では、トランザクションがステートメント内で使用されているテーブルのメタデータロックと同等のロックを獲得した場合、ステートメントの終了時にロックを解放していました。このアプローチには、アクティブなトランザクションで別のセッションによって使用されているテーブルに対して、DDL ステートメントが実行された場合、ステートメントは誤った順序でバイナリログに書き込まれる可能性があるという欠点がありました。


User Comments
  Posted by Mohamed Nabil on October 6, 2013
If you have a desktop program with multi-user connections to database that freezes when you try to Lock Tables using statement "LOCK TABLES table_1 WRITE, table_2 WRITE, table_n WRITE"
then in mysql command line tool run command "SHOW FULL PROCESSLIST;"
If you faced the problem of "Waiting for table metadata lock" then consider the following

After Reading the resource attached down here I could figure out my problems was:
1- Since 5.5 any table accessed during a transaction its meta data is locked by mysql
2- Since in transactional database desktop application are transaction enabled all the time then JDBC connection is set always to be connection.setAutoCommit(false);
3- running complete successful transaction with commit/rollback methods will release any locks held by mysql during this successful transaction
4- any next call to select statements queries is considered a transactional operation and then metadata are held locked by mysql server
5- again if you run a select stament only queries then all these selected tables metadata are held locked by mysql server
6- you have to call commit/rollback to release these tables metadata even if you had never executed Update/Delete statements in your queries
7- as a solution you have to:
a- when use connection.setAutoCommit(false); you have to run commit or rollback after every select statement you make to release metadata locks and allow other sessions can run select queries on tables you used.
b- use connection.setAutoCommit(true); for the life of connection and switch the use to be connection.setAutoCommit(false); when making Update/Delete commit/rollback transactional operations to avoid the metadata lock situations

Please Note that running rollback is much safer (losing valuable data is better than injecting wrong data) in this situation, for me now I attached connection.rollback() after calling select-only statements queries statement.close(); to keep connection.setAutoCommit(false); during connection life time.

for further discussion read my post here:
http://stackoverflow.com/questions/19203455/jdbc-mysql-lock-tables-freeze

Resources:
============
http://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html
Before MySQL 5.5, when a transaction acquired the equivalent of a metadata lock for a table used within a statement, it released the lock at the end of the statement. This approach had the disadvantage that if a DDL statement occurred for a table that was being used by another session in an active transaction, statements could be written to the binary log in the wrong order.

http://bugs.mysql.com/bug.php?id=60563
Also, just to make it clear, if a statement inside a transaction ever access a table, a metadata lock is kept on the table until the transaction is either committed or rolled back. For example:

session 1>
BEGIN;
SELECT * FROM t1;

session 2>
ALTER TABLE t1 ADD PARTITION ...;

Even after the SELECT has been executed, the ALTER TABLE won't succeed until session 1 either commits or rollbacks the transaction.
The statement might have been run inside a transaction that hasn't been properly ended (commit/rollback).
Sign Up Login You must be logged in to post a comment.