快乐学习
前程无忧、中华英才非你莫属!

Day12-解决MySQL_ERROR参考指南(元数据锁)

2.4 元数据锁
 
为了确保数据一致性,在有其他事务使用表的情况下,对该表的DDL操作应该阻塞。从5.5.3版本开始,MySQL使用元数据锁来实现这一特性。当事务开始的时候,它会获取所有需要使用的表上的元数据锁,并在事务结束后释放锁。所有其他想要修改这些表定义的线程都需要等待事务结束。5.5.3版本之前的MySQL上的DDL操作没有并行事务的概念。这会导致类似下面的冲突:
 
一个事务中,我们从表中查询数据,并计划在当前事务中使用该查询的结果集。与此同时,另一个线程删除表:
 
 
 DROP是不可回滚的操作,因此第一个线程因为冲突受到了影响:
 该事务显然不能正常完成。而元数据锁则可以在其他连接执行DROP语句之前,让该事务正常完成。为了举例说明这个特点,我们在5.5.3或之后的版本上执行同样的例子。
 
现在再试图执行DROP会被阻塞:
 
 在执行完这条命令后,我等待了若干秒,这样你就会知道drop执行了多久,然后我才回滚第一个事务:
 现在我们可以看一下查询的执行时间,确认DROP操作是等待第一个事务执行完成才执行的: 
新模型更安全,并且这种方式不再需要掌握任何新的排错技术。不过MySQL在元数据锁引入之前已经存在很久了,并且很多用户已经熟悉了老的操作习惯,甚至为其定制了工作方案。因此,我打算增加一些说明来介绍服务器行为中因元数据锁而产生的不同。
 
元数据锁对比旧的模型
 
元数据锁的获取不依赖于使用的存储引擎。因此,无论使用的是设置autocommit=0的MyISAM引擎还是用BEGIN或START TRANSACTION语句显式声明的事务,连接都会取得元数据锁。可以在SHOW- PROCESSLIST的输出中清楚地看到这些信息,在输出中你会看到一些状态为“Waiting for table metadata lock”的语句。用一个小示例来说明元数据锁的使用。第一个线程启动一个事务以访问MyISAM引擎的表。这里使用了BEGIN语句,不过如果设置autocommit=0也会产生同样的效果:
同时,另一个线程调用TRUNCATE命令,该命令会对表的元数据产生影响:
 
 
通过第三个连接来执行SHOW PROCESSLIST命令,可以看到前面两个线程的状态:
 
当一个查询在等待元数据锁的时候被阻塞,可以使用SHOW PROCESSLIST命令。当迁移到支持元数据锁的MySQL版本之后,你会发现DDL查询开始变慢了。这是因为当其他事务持有锁的时候它们不得不等待。从理论上来说,元数据锁会超时。可以通过lock_wait_timeout变量指定超时时间。默认是31 536 000秒(一年),所以实际上锁住的查询永远不会终止
为使超时有效果,可以设置lock_wait_timeout为一个较小的值,例如一秒:
 
 
 
打赏

未经允许不得转载:同乐学堂 » Day12-解决MySQL_ERROR参考指南(元数据锁)

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

特别的技术,给特别的你!

联系QQ:1071235258QQ群:226134712
error: Sorry,暂时内容不可复制!