mysqlでテーブルメタデータロックを待機する理由と解決策

http://www.cnblogs.com/dyllove98/archive/2013/07/16/3194332.html


実经常態到mysql数データベース库死锁、郁闷死、プロセスリストを 
表示; 時間テーブルメタデータロックを待機しています能一直锁很久給有官 


0042的一段话、可聴下 
http://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html8.10.4 


メタデータロック 
MySQL5.5.3以降では、メタデータロックを使用して、オブジェクト(テーブル、トリガーなど)へのアクセスを管理します。メタデータロックは、データの整合性を確保するために使用されますが、クエリ量が増えると増加するオーバーヘッドが発生します。メタデータの競合は、複数のクエリが同じオブジェクトにアクセスしようとするほど増加します。 


メタデータロックはテーブル定義の場合に代わるものではなく、そのミューテックスとロックはLOCK_openミューテックスとは異なります。以下の説明は、メタデータロックがどのように機能するかについての情報を提供します。 


トランザクションの直列化可能性を確保するために、サーバーは、あるセッションが別のセッションの未完了のトランザクションで使用されるテーブルに対してデータ定義言語(DDL)ステートメントを実行することを許可してはなりません。サーバーは、トランザクション内で使用されるテーブルのメタデータロックを取得し、トランザクションが終了するまでそれらのロックの解放を延期することでこれを実現します。テーブルのメタデータロックは、テーブルの構造の変更を防ぎます。このロックアプローチには、1つのセッション内のトランザクションで使用されているテーブルを、トランザクションが終了するまで他のセッションでDDLステートメントで使用できないという意味があります。 


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


トランザクションを開始します。 
SELECT * FROM t; 
SELECT * FROM nt; 
メタデータロックは、トランザクションが終了するまでtとntの両方で保持されます。別のセッションがいずれかのテーブルでDDL操作を試行すると、トランザクションの終了時にメタデータロックが解放されるまでブロックされます。たとえば、2番目のセッションは、次のいずれかの操作を試行するとブロックされます 


。DROPTABLE t; 
ALTER TABLE t ...; 
ドロップテーブルnt; 
ALTER TABLE nt ...; 
サーバーは、構文的には有効であるが実行中に失敗したステートメントのメタデータロックを取得した場合、ロックを早期に解放しません。失敗したステートメントはバイナリログに書き込まれ、ロックによってログの整合性が保護されるため、ロックの解放はトランザクションの終了まで延期されます。 


In autocommit mode, each statement is in effect a complete transaction, so metadata locks acquired for the statement are held only to the end of the statement. 


Metadata locks acquired during a PREPARE statement are released once the statement has been prepared, even if preparation occurs within a multiple-statement transaction. 


Before MySQL 5.5.3, 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 


一个没提交的事务使用了A表, 另外一个session 对A表进行alter,出现waiting for table metadata lock 


在insert into t select * from share 运行时, 同时执行alter table t add index(play_count), 
alter table语句会Waiting for table metadata lock, 直到insert into … select 语句结束。 


不是传说5.6支持online DDL么? 怎么还会Waiting for table metadata lock? 
后来想想, online DDL应该是指在alter table进行的时候, 插入/修改/删除数据的sql语句不会Waiting for table metadata lock. 


MySQL 5.6 enhances many other types OF ALTER TABLE operations TO avoid copying the TABLE.  
Another enhancement allows SELECT queries AND INSERT, UPDATE, AND DELETE (DML) statements TO proceed while the TABLE IS being altered.  
This combination OF features IS now known AS online DDL. 
那么就让alter table wait去吧。 


后来又发现另外一个神奇的事: 
mysql [localhost] {msandbox} (spc) > SHOW processlist; 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
| Id | USER     | Host      | db   | Command | TIME | State                           | Info                                | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
|  5 | msandbox | localhost | spc  | Query   |    1 | Waiting FOR TABLE metadata LOCK | ALTER TABLE t ADD INDEX(play_count) | 
|  8 | msandbox | localhost | spc  | Query   |    3 | USER sleep                      | SELECT sleep(100) FROM t            | 
| 10 | msandbox | localhost | spc  | Query   |    0 | init                            | SHOW processlist                    | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 


重启后再试一次: 
mysql [localhost] {msandbox} (spc) > SHOW processlist; 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
| Id | USER     | Host      | db   | Command | TIME | State                           | Info                                | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
|  1 | msandbox | localhost | spc  | Query   |  129 | USER sleep                      | SELECT sleep(100) FROM t            | 
|  2 | msandbox | localhost | spc  | Query   |  102 | Waiting FOR TABLE metadata LOCK | ALTER TABLE t DROP INDEX play_count | 
|  3 | msandbox | localhost | spc  | Query   |    0 | init                            | SHOW processlist                    | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 


这个sleep的时间。。。已经超过100秒了… 


结论: 
在准备alter table tbl 的时候,先观察一下,有没有正在运行的,且在短时间内无法结束的sql语句在操作tbl表

おすすめ

転載: blog.csdn.net/huochuangchuang/article/details/49423893
おすすめ