当前位置:C++技术网 > 资讯 > mysql锁表解锁数据表问题分析和解决方法总结

mysql锁表解锁数据表问题分析和解决方法总结

更新时间:2017-10-27 10:38:14浏览次数:1+次

        昨天在操作一个mysql数据表时,发现执行了数据表操作的代码一直都不返回,等了很久才返回超时错误。然后我就用数据库工具Navicat执行语句,发现查询语句没有问题,然而更新语句却卡死了。然后重启了数据库服务,再重试更新语句,依然卡死。

        后面试了一下重命名表,结果又卡死了。Navicat工具都卡死了。可以非常确定的是,数据库语句没有任何问题,因为我在另外一个同步数据库里执行了,一切正常。两个数据库是一样的结构。

        今天准备删表了的。打算删表之后,用备份数据库的表来重建一个表。不过这样做还是有点冒险,谁知道还会遇见什么问题。本着解决问题的心态,还是去找了一下这个表的问题。

        查询资料可以大概确定这个表可能是被锁定了。如何锁定,以及具体锁定的状态都不得而知。此前没有遇见过这个情况,对这个也不知道如何查询。网上查阅的一些资料,产生了误导,各种乱七八糟的语句,都无济于事。

        今天直接查询了一下数据表的解锁,然后就看到一个很有用的语句:

    show processlist;

        查看数据库的进程列表。查出来的结果如下图所示:

    mysql锁表解锁数据表问题分析和解决方法总结

        Id字段是进程的ID,重点是State。这个表示的是状态,从英文的描述里,可以看到,Waiting for table metadata lock就是等待被锁的表。在Info字段可以看到描述的内容中看到表名。也就是说,操作的这个表已经被锁定,当前操作需要等待此表被解锁才可以继续执行。所以出现最开始描述的各种卡死现象。

        而这个一切的源头,都来自Id为2的这个语句的执行,导致后续的语句全挂了。具体锁表的原因不太清楚,有可能是执行了语句没有commit造成的。

        可能有人从来没有执行过上面这个语句,所以可能不知道在哪里执行。我一开始用这个语句的时候也是不知道在哪执行,只能试一下。这个就是一个正常的SQL语句,所以如何执行SQL语句,就如何执行这个语句。上图的结果就是执行此语句的结果,和其他SQL语句没有什么差别。

        既然找到了表被锁的证据,如何解锁表呢?在上图中我们看到了锁表的进程Id,那么我们直接干掉这个进程就好了。说到这里,其实这个问题还有一个更快的解决办法,那就是重启操作系统。进程就不存在了,就没有死锁的问题了。

        不过还是本着解决问题的思路,看看如何杀死这个进程吧。

        同样,我们还是执行SQL语句来杀死进程。在SQL世界里,什么都是sql语句,没有Sql语句不能解决的问题,这是基本思想。所以不要想着去操作系统里杀进程,不是不行,而是不必要。数据库自家的矛盾自家解决就好了。

        杀进程的语句如下:

    kill 进程ID;

        所以我执行了“kill 2;”,执行完后提示执行成功。接下来神奇的事情就发生了。执行查询的一个语句,一下就显示所有的数据了。然后又发现,再去找这个表的时候,提示表不见了。吓我一跳。然后很快,出现了另外一个表名,不过很熟悉,那就是我之前重命名的表名。然后再重命名回来,查询。一切正常。这一切的过程因为进程id为2的进程被干掉之后,就全部启动了执行,然后就有了这一系列的连续动作。

        而网上一大堆资料,说的乱七八糟,误导了我。今天思路一捋顺,分分钟解决了这个问题。