------------------+
| Id | User | Host ?| db ?| Command | Time | State | Info |
+----+------+-----------+---------+---------+------+-------+------------------+
| ?1 | root | localhost | ngx_lua | Sleep ? | 3757 | ? | NULL |
| ?2 | root | localhost | ngx_lua | Query ? |0 | init ?| show processlist |
+----+------+-----------+---------+---------+------+-------+------------------+
2 rows in set (0.01 sec)
?
mysql>
?
然而看到,kill 3 并没有使 metadata lock 得到释放。使用了 unlock tables; 语句才释放了 metadata lock。最后那个select 语句也得以执行完成。
?
注意:lock table cats read; 语句并不会一致持有 metadata lock 而阻塞其它语句。
?
11. 实验二
?
首先在A终端中修改 autocommit 参数:
?
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
?
mysql> show session variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit| OFF ? |
+---------------+-------+
1 row in set (0.00 sec)
?
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
?
mysql> select * from cats;
+----+------+
| id | name |
+----+------+
| ?3 | NULL |
| ?2 | ?|
| ?1 | Andy |
+----+------+
3 rows in set (0.01 sec)
?
首先修改 session 的 autocommit 参数为 off, 然后开始一个事务。注意该事务一直没有提交。
?
然后在终端B中执行一条DDL语句:
发现被阻塞了。而阻塞它的就是那个没有提交的事务,因为他一致持有 metadata lock,所以导致DDL语句被阻塞。
?
?
mysql> show processlist;
+----+------+-----------+---------+---------+------+---------------------------------+----------------------------------+
| Id | User | Host ?| db ?| Command | Time | State ? | Info |
+----+------+-----------+---------+---------+------+---------------------------------+----------------------------------+
| ?1 | root | localhost | ngx_lua | Query ? |0 | init| show processlist |
| ?2 | root | localhost | ngx_lua | Query ? | ?177 | Waiting for table metadata lock | alter table cats drop index name |
| ?4 | root | localhost | NULL| Sleep ? | ?322 | | NULL |
+----+------+-----------+---------+---------+------+---------------------------------+----------------------------------+
3 rows in set (0.00 sec)
?
手动 commit 之后,DDL的阻塞结束,顺利执行完成。
?
mysql> alter table cats drop index name;
Query OK, 0 rows affected (4 min 30.81 sec)
Records: 0 ?Duplicates: 0 ?Warnings: 0
可以看到阻塞了 (4 min 30.81 sec)
?
上面两个实验说明:DDL 语句以及lock table xxx write 和 事务 对 metadata lock 存在互斥争用。
?
12. 实验三
?
在终端A(autocommit=off)中执行:
?
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit| OFF ? |
+---------------+-------+
1 row in set (0.00 sec)
?
mysql> update cats set name='Linus' where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 ?Changed: 1 ?Warnings: 0
?
然后在终端B(autocommit=on)中执行:
?
mysql> update cats set name='strup' where id=3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 ?Changed: 1 ?Warnings: 0
可以看到终端B并没有被阻塞。
?
即使A,B都是 autocommit=off, 并且都不提交,都存在事务中,也不会相互阻塞。这说明普通的update,select,delete并不会在metadata lock上争用,也就是多个运行中的事物可以同时持有同一个database object上的metadata lock(因为这些非DDL语句并不会修改database objects,它们修改的是表数据而不是表结构).
?
13. 实验四
?
首先在A终端中,设置 autocommit=off; 然后随便执行一条update,select,delete语句:
?
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| aut