metadata lock的超时时间是lock_wait_timeout,并不是innodb_lock_wait_timeout
MySQL 5.5.3版本中引入了Metadata lock: DDL语句打破了事务的隔离级别
在5.5.3版本之前,MySQL事务对于表结构元数据(Metadata)的锁定是语句(statement)粒度的, 即语句执行完成后,不管事务是否可以完成,其表结构就可以被其他会话更新掉!
引入Metadata lock后,表结构元数据(Metadata)的锁定变成了事务(transaction)粒度的,即只有事务结束时才会释放Metadata lock。
现象:
显式开启事务后start transaction; 该事务内的query语句(包含select)会占用相关表的metadata lock(profile:Opening tables阶段)
导致DDL语句被阻塞,因为获取不到表的metadata lock
MySQL 5.6.6版本后 优化
metadata lock不阻塞DDL语句,但原有session再访问此表时会返回Error信息“Table definition has changed, please retry transaction”
案列
- session1
-
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test1 where id=1;
+------+------+
| id | name |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec) -
- session2
-
-
mysql> set profiling=on;
- Query OK, 0 rows affected (0.00 sec)
-
mysql> alter table test1 add column c2 int; - ---堵塞
-
-
mysql> show full processlist;
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
| 4 | root | localhost | test | Sleep | 10 | | NULL |
| 5 | root | localhost | test | Query | 6 | Waiting for table metadata lock | alter table test1 add column c2 int |
| 6 | root | localhost | NULL | Query | 0 | NULL | show full processlist |
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
我们可以看到ALTER TABLE会应Metadata lock而阻塞。一旦Session 1中的事务提交或者回滚,即释放了table1表的Metadata lock,Session2的操作立即可以执行
- ctrl+c掉后我们查看profile执行计划
-
-
mysql> show profile for query 6;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000045 |
| checking permissions | 0.000005 |
| checking permissions | 0.000005 |
| init | 0.000007 |
| Opening tables | 0.000061 |
| System lock | 0.000008 |
| setup | 0.000018 |
| creating table | 0.002776 |
| After create | 0.000063 |
| copy to tmp table | 0.000312 |
| rename result table | 1.459601 |
| query end | 0.000031 |
| closing tables | 0.000285 |
| freeing items | 0.002271 |
| cleaning up | 0.000073 |
+----------------------+----------+
15 rows in set (0.00 sec)
可以看到,卡住的那一步是在rename result table,MySQL后台将ALTER保存变成连续操作“创建临时新表->插入老表的数据->临时新表取到老表(RENAME)”,即实际的变化老表的操作在RENAME阶段才发生。而这一步即是被阻塞的那一步。所以可以确认,Metadata lock影响到的是要真实修改表结构的动作。(回想:和pt-osc那节,一个select未执行完,alter 修改表结构产生metadata lock一个道理)
基于此,我们可以验证ALTER TABLE,RENAME TABLE,DROP TABLE都会被Metadata lock影响,验证步骤与上类似,省略。
值得注意的是,创建一个已存在的表也会被Metadata lock影响。如果在一个事务中用到了表A的Metadata lock(如SELECT了该表)且事务未完成,那么创建同名的表也会被卡住。所参考的文章中提及这一点。有兴趣可参看:讨论页 ,这里不作讨论。
metadata lock的另一个副作用:如上例中,ALTER TABLE应metadata lock被阻塞后,这导致后续其他事务针对该表的SELECT也会被阻塞!即ALTER TABLE的操作会影响到其他SELECT操作。根据上述示例:
Session2 mysql> alter table table1 add column c1 int;
此步一直处于等待状态时,新会话中查询table1。
Session3 mysql> select * from test1; #一直等待
Session4 mysql>show full processlist;
mysql> show full processlist;
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
| 4 | root | localhost | test | Sleep | 1857 | | NULL |
| 5 | root | localhost | test | Query | 504 | Waiting for table metadata lock | select * from test1 |
| 6 | root | localhost | NULL | Query | 0 | NULL | show full processlist |
| 8 | root | localhost | test | Query | 511 | Waiting for table metadata lock | alter table test1 add column c2 int |
+----+------+-----------+------+---------+------+---------------------------------+-------------------------------------+
Session1 mysql> commit;
第一个会话提交后,Session2、Session3也成功执行。看看Session3的select在哪个步骤需要等待:
Session3 mysql> show profile;
+——————————–+———–+
| Status | Duration |
+——————————–+———–+
| starting | 0.000018 |
| Waiting for query cache lock | 0.000003 |
| checking query cache for query | 0.000037 |
| checking permissions | 0.000007 |
| Opening tables | 22.502591 |
| System lock | 0.000013 |
| Waiting for query cache lock | 0.000024 |
| init | 0.000022 |
| optimizing | 0.000009 |
| statistics | 0.000011 |
| preparing | 0.000015 |
| executing | 0.000003 |
| Sending data | 0.000036 |
| end | 0.000009 |
| query end | 0.000005 |
| closing tables | 0.000006 |
| freeing items | 0.000007 |
| Waiting for query cache lock | 0.000003 |
| freeing items | 0.000015 |
| Waiting for query cache lock | 0.000002 |
| freeing items | 0.000002 |
| storing result in query cache | 0.000004 |
| logging slow query | 0.000002 |
| logging slow query | 0.000028 |
| cleaning up | 0.000003 |
+——————————–+———–+
可以看到SELECT语句首先检查查询缓存,没有命中,然后在Opening tables阶段卡住。
这引出了另一个特点,基于上述场景,如果后续的SELECT能够在查询缓存中命中,那么不会被ALTER TABLE卡住,因为不需要Opening tables操作。命中缓存SELECT的SHOW PROFILE如下:
mysql> show profile;
+——————————–+———-+
| Status | Duration |
+——————————–+———-+
| starting | 0.000017 |
| Waiting for query cache lock | 0.000004 |
| checking query cache for query | 0.000006 |
| checking privileges on cached | 0.000004 |
| checking permissions | 0.000007 |
| sending cached result to clien | 0.000011 |
| logging slow query | 0.000002 |
| cleaning up | 0.000003 |
+——————————–+———-+
8 rows in set (0.00 sec)
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756
相关文章
发现更多好内容- Java 中线程间通信的方法有哪些?(java线程间通信的方法是什么)
- Java 多线程批量处理的方法究竟有哪些?(java多线程批量处理的方法是什么)
- Java 中 BigDecimal 的详细介绍与实用使用方法(java中BigDecimal的介绍及使用)
- 如何通过 JavaScript 事件循环来优化代码?(JavaScript 事件循环如何优化代码)
- 如何用 Java 解析 XML 并获取标签属性值?(java怎么解析xml获取标签属性值)
- Java 中实现 MapReduce 的具体方法有哪些?(java实现mapreduce的方法是什么)
- 如何让 Java 的 settimeout 与线程池协同工作?(Java settimeout怎样与线程池配合)
- Java 中对象数组的定义及使用方式有哪些?(Java对象数组定义与用法有哪些)
- Java ClassLoader 的使用方法究竟是什么?(java classloader的使用方法是什么)
- Java 中 Bimap 的适用场景具体有哪些?(Bimap在Java中的适用场景有哪些)
猜你喜欢
AI推送时光机【Mysql】metadata lock锁
数据库2024-04-02MySQL metadata lock阻塞问题
数据库2024-04-02MySQL表结构怎样变更Metadata Lock
数据库2024-04-02Waiting for table metadata lock
数据库2024-04-02mysql 间隙锁 Gap Lock
数据库2024-04-02Metadata Lock在MySQL数据库中有什么作用
数据库2024-04-02如何进行MySQL metadata锁实验
数据库2024-04-02如何理解mysql innodb lock锁中的record lock
数据库2024-04-02mysql 元数据锁 Meta Data lock
数据库2024-04-02MySQL中next-lock锁的应用
数据库2024-04-02咦!没有更多了?去看看其它编程学习网 内容吧 -
mysql> set profiling=on;