关于更新表结构时碰到的DDL锁导致数据库无法连接

记一次更新表结构时语句一直处于等待无法执行的解决办法

我们在更新数据库表结构的时候,当数据库有连接正在进行中的事务时,那么你的更新请求会处于一个等待的状态,一直等待到当前未提交的事务完成之后才会进行更新操作,但是这个未提交的事务会需要多久时间完成对我们来讲是一个未知数,(自己第一次碰到这个情况的时候,竟然以为是数据记录太多需要等待更新,等了半个小时... 愚蠢)在这个等待期间,所有的后续连接请求都会被挂起,等待事务提交完成后更新操作完成才会执行,逻辑是这样的:有个事务1在查询表a,一直占着不释放,那么这个时候执行ddl操作,就会被事务1阻塞,直到事务1被提交或者被kill。如果当你在更新表结构时碰到了这种情况,不要等,等的越久你会发现自己越蠢。

首先说一下我们在执行ddl操作前需要注意的几点:

第一点:

  不要使用navicat等第三方工具进行该操作,在你使用sql语句时,卡死掉我们ctrl+c结束正在执行的语句就好了,但是当我们利用navicat这种第三方工具连接时,一旦语句卡死,navicat这个程序也会无响应,并且!你将程序进程结束掉仍然无法停止正在执行的语句!(大坑!)

第二点:

  在更新前要挑选一个业务的低峰期进行更新,这个是在询问阿里怎样避免因为更新时出现此机制影响线上环境时阿里告诉我的办法,emmm...

接下来说一下碰到这种问题时我们应该怎么去解决:

第一点:

  我们在执行ddl操作前可以执行一下 select * from information_schema.innodb_trx 来看一下我们当前有没有未提交的事务,可根据结果中的trx_state来看当前线程的状态

第二点:

  在上条语句的查询结果中我们可以找到有一个trx_mysql_thread_id列,这个列名对应的值我们可以在show processlist中找到对应的记录,找到后可以查看对应记录的host列以及对应的用户和库,说明该主机还有连接没有断开

第三点:

  在找到这些信息之后我们判断该条连接是否可以kill,如果可以,我们可以 kill id(替换为对应连接的trx_mysql_thread_id) 之后再进行ddl操作

  这时没有了未提交需要等待的事务,我们的表结构更新语句便会顺利执行成功。

 

SQL语句大致分为三种类型

DML:数据操纵语言

  就是我们最经常用到的 SELECT、UPDATE、INSERT、DELETE。 主要用来对数据库的数据进行一些操作。

DDL:数据库定义语言

  就是我们在创建表的时候用到的一些sql,比如说:CREATE、ALTER、DROP等。DDL主要是用在定义或改变表的结构,数据类型,表之间的链接和约束等初始化工作上。其中最大可能触发锁机制的就是ALTER。

DCL:数据库控制语言

  是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。这个比较少用到。

posted @ 2018-11-07 15:41  *白小生*  阅读(572)  评论(0编辑  收藏  举报