开发环境经常出现DML语句或者DDL语句被block住的情况解释

问题: 如题

分析过程:
9846926 test 192.168.12.91:42638 test Query 3852 Waiting for table metadata lock
==============================================================================================
alter table order \n modify gmt_timeout datetime comment '超时时间' 0 0 1
show engine innodb status\G
可以看到:
---TRANSACTION 5AD02DA82, ACTIVE 4212 sec
2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 9846603, OS thread handle 0x7ff5e2df8700, query id 11878319368 10.13.134.143 bbc
TABLE LOCK table `test`.`order` trx id 5AD02DA82 lock mode IX
RECORD LOCKS space id 199033 page no 3 n bits 120 index `PRIMARY` of table `test`.`order` trx id 5AD02DA82 lock_mode X locks rec but not gap
----------------------------
END OF INNODB MONITOR OUTPUT
============================
可以看到这个语句执行不下去,是因为被锁住了,我们再继续观察:
root@(none) 12:59:19>select trx_id,trx_state,trx_mysql_thread_id,trx_isolation_level,trx_rows_modified,trx_started from information_schema.innodb_trx;
+-----------+-----------+---------------------+---------------------+-------------------+---------------------+
| trx_id | trx_state | trx_mysql_thread_id | trx_isolation_level | trx_rows_modified | trx_started |
+-----------+-----------+---------------------+---------------------+-------------------+---------------------+
| 5AD997BB7 | RUNNING | 9831682 | READ COMMITTED | 0 | 2013-04-03 12:59:38 |
| 5AD02DA82 | RUNNING | 9846603 | READ COMMITTED | 0 | 2013-04-03 11:42:54 |
+-----------+-----------+---------------------+---------------------+-------------------+---------------------+
2 rows in set (0.04 sec)
确实没提交,如果要想让线程9846926继续执行,解决办法:kill 9846603.
原因:日常环境开发同学经常断点调试,导致有些事务打开了没有关闭,所以等下下次调试,操作同一条记录的时候就会被阻塞,日常环境99%的情况是因为这个。
还有另外一种情况innodb层静态数据的统计,解决办法:set global innodb_stats_on_metadata=0

问题重现:

CREATE TABLE `xdual` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `x` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `v` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_x` (`x`),
  KEY `idx_v` (`v`)
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8;

root@test 07:40:10>select * from xdual;
+----+---------------------+------+
| id | x                   | v    |
+----+---------------------+------+
|  2 | 2012-04-19 20:25:40 |    1 |
|  4 | 2012-04-18 00:53:58 |    3 |
|  6 | 2012-04-18 00:54:00 |    5 |
|  8 | 2012-04-18 18:23:16 |    7 |
| 10 | 2012-04-18 00:54:03 |    2 |
| 12 | 2012-04-18 02:26:13 |    4 |
| 14 | 2012-04-18 00:54:06 |    6 |
| 15 | 2012-04-18 02:26:13 |    4 |
| 16 | 2012-04-18 18:24:14 |    7 |
| 18 | 2012-04-18 00:54:10 |    8 |
| 22 | 2012-04-18 15:12:08 |   18 |
| 26 | 2012-04-18 18:23:16 |    7 |
| 34 | 2012-04-18 02:30:09 |    4 |
+----+---------------------+------+  
MySQL5.5.16    innodb_stats_on_metadata=OFF

         session 1                                |       session 2                                  | session 3 
begin;                                            |                                                  |
update xdual set v=20 where id=34;                |                                                  |
                                                  |alter table xdual modify `v` int(11) DEFAULT NULL;|
                                                  |                                                  |
                                                  |                                                  |
                                                  |                                                  |9915844    Waiting for table metadata lock                                                     |                                                  |   
                                                  |                                                  |=============================================
                                                  |                                                  | alter table xdual modify v int DEFAULT NULL                                                   |                                                  |  
                                                  |                                                  |
alter table xdual modify `v` int(11) DEFAULT NULL;|                                                  |                                                                                               |                                                  |
                                                  |                                                  |session 2 metalock lock 解除
                                                  |                                                  |
                                                  |                                                  |
                                                  |Query OK, 0 rows affected (1 min 24.35 sec)       |                                         
                                                  |Records: 0  Duplicates: 0  Warnings: 0            |                                         
                                                  |                                                  |
root@test 07:43:50>commit;                        |                                                  |
                                                  |                                                  |
                                                  |                                                  |
                                                                     
 MySQL5.1.48
CREATE TABLE `test_lingluo` (                                                                             
  `id` bigint(20) unsigned NOT NULL,                                                                      
  `biz_order_id` int(11) NOT NULL,                                                                        
  `parent_id` int(11) NOT NULL,      
  `auction_id` int(11) NOT NULL,     
  `sku_id` int(11) NOT NULL,         
  `field5` varchar(20) NOT NULL,     
  PRIMARY KEY (`id`),                
  KEY `idx_sku_id` (`sku_id`),       
  KEY `idx_auction_id` (`auction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
root@test 07:21:01>select * from test_lingluo;                   
+----+--------------+-----------+------------+--------+--------+
| id | biz_order_id | parent_id | auction_id | sku_id | field5 |
+----+--------------+-----------+------------+--------+--------+
|  1 |            1 |         1 |        123 |    123 | fffff  |
|  2 |            2 |         2 |        321 |    321 | aaaaa  |
|  3 |            3 |         3 |        456 |    456 | fffff  |
|  4 |            4 |         4 |          4 |      4 | eeee   |
|  5 |            5 |         5 |          5 |      5 | dddd   |
|  6 |            6 |         6 |          6 |      6 | cccc   |
|  7 |            7 |         7 |          7 |   1000 | dddd   |
|  8 |            8 |         8 |          8 |    100 | dddd   |
|  9 |            9 |         9 |          9 | 100000 | fffff  |
| 10 |           10 |        10 |         10 |      1 | dddd   |
+----+--------------+-----------+------------+--------+--------+
10 rows in set (0.00 sec)

              session 1                           |          session 2                                             |       session 3 
begin;                                            |                                                                |
update test_lingluo set field5='yyyy' where id=10;|                                                                |
                                                  |                                                                |
                                                  |alter table test_lingluo modify field5 varchar(30) default null;|
                                                  |                                                                |
                                                  |                                                                |1232570045    copy to tmp table                                                  |                                                                |   
                                                  |                                                                | ==============================
                                                  |                                                                | alter table test_lingluo modif                                                  |                                                                |   y field5 varchar(30) 
| | default null | | | | | | commit; | |metalock 解除 | |

背景知识:

Metadata Locking

To ensure transaction serializability, the server must not permit one session to perform a data definition language (DDL) statement on a table that is used in an uncompleted transaction in another session. The server achieves this by acquiring metadata locks on tables used within a transaction and deferring release of those locks until the transaction ends. A metadata lock on a table prevents changes to the table's structure. This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.

除去99%的情况,还有另外一种,丁奇已经解释过了,关于metadata lock

posted @ 2013-04-03 20:20  sunss  阅读(634)  评论(0)    收藏  举报