<>强语句(声明)粒度强>
<强>事务(事务)粒度强> <强>即只有事务结束时才会释放元数据锁。强>
-
<李>
session1
李>
<李>
mysql>开始事务;
查询好,0行影响(0.00秒)
mysql>select * test1中id=1;,,
+ - - - - - - - - - - - - + +
| id,| |名称
+ - - - - - - - - - - - - + +
|,1 | 1大敌;,|
+ - - - - - - - - - - - - + +
1行集(0.00秒) 李> <李>
李> <李> session2 李> <李>
-
<李>
设置profilingon
李> <李> 查询好0行影响000秒 李> <李> 李> <李> 李> <李> 李> <李> c2 int | | alter table test1添加列,
6根| | |,localhost零| |查询,|,,0 |空,,,,,,,,,,,,|显示完整processlist大敌;,,,,,,|
+ - - - + - - - + - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
李> <李> 李> <李> 李> <李> |,,
|查询结束,,,,,0.000031,| |
|关闭表,,,| 0.000285 |
|释放物品,,,0.002271,| |
|清理,,,,0.000073,| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
15行集(0.00秒)
可以看的到,卡住的那一步是在重命名结果表,MySQL后台将改变保存变成连续操作“<>强创建临时新表→插入老表的数据→临时新表取到老表(重命名)>强”,即实际的变化老表的操作在重命名阶段才发生。而这一步即是被阻塞的那一步。所以可以确认,<强> 强>
基于此,我们可以验证ALTER TABLE,重命名表,删除表都会被元数据锁的影响,验证步骤与上类似,省略。
值得注意的是,创建一个已存在的表也会被元数据锁影响。如果在一个事务中用到了锁表的元数据(如选择了该表)且事务未完成,那么创建同名的表也会被卡住。所参考的文章中提及这一点。有兴趣可参看:讨论页,,这里不作讨论。
元数据锁的另一个副作用:如上例中,改变表应元数据锁被阻塞后,这导致后续其他事务针对该表的选择也会被阻塞!即ALTER TABLE的操作会影响到其他选择操作,根据上述示例:
此步一直处于等待状态时,新会话中查询表。
,#一直等待
中第一个会话提交后,Session2, Session3也成功执行。看看Session3的选择在哪个步骤需要等待:
可以看到选择语句首先检查查询缓存,没有命中,然后在打开表阶段卡住。
这引出了另一个特点,基于上述场景,如果后续的选择能够在查询缓存中命中,那么不会被ALTER TABLE卡住,因为不需要打开表操作。命中缓存选择的显示配置文件如下:
mysql>,显示配置文件;
+ - - - - - - - - - - - - + - - - +
| Status ,,,,,,,,,,,,,,,,,,,,,,,| |时间
+ - - - - - - - - - - - - + - - - +
| starting ,,,,,,,,,,,,,,,,,,,,,| 0.000017 |
|等待查询缓存lock ,| 0.000004 |
检查查询缓存查询| | 0.000006 |
cached  |查看权限;| 0.000004 |
|检查permissions ,,,,,,,,,| 0.000007 |
|发送缓存结果clien | 0.000011 |
|登录缓慢query ,,,,,,,,,,,| 0.000002 |
|清洁up ,,,,,,,,,,,,,,,,,,| 0.000003 |
+ - - - - - - - - - - - - + - - - +
8行集(0.00秒)
李>
李>
<强>遗留问题1。为什么第二次查询,记录没有发生变化,但结果集返回空? 强>
这个问题在这个页面进行了讨论,确认原因是: