DBA的日常苦恼
日常工作中,你是否有这样的经历:非生产环境中,由于开发小伙伴不按套路出牌,DDL与DML并发执行,导致许多会话受到阻塞,大量会话出现等待元数据锁,数据库连接数激增。虽然生产环境要求操作规范,规定不在业务高峰期执行DDL操作,但有时因业务SQL执行慢,不得不紧急创建索引来提速,也会发起DDL。因此,当遇到DDL与DML互相阻塞这类问题时,应如何快速定位并解决问题呢?话不多说,直接上案例~
DBA线上故障演练场
包拯DBA小组成员偶遇,一起闲话聊家常~
王朝
大人,我们安全数据库GreatDB分布式支持ONLINE-DDL吗?
当然,这个功能在之前版本就已经支持了。
包拯
王朝
我咋听说上次展大哥在某某并行环境创建索引,引起了数据库连接数激增,CPU资源告警啦!
快说说,展哥犯啥错误了,我们也吸取一下教训。
马汉
此时,展昭正好走进来听到对话,面露不悦之色……
包拯
既然你们都好奇,那今天就对此问题做一次故障演练,方便你们在遇到问题时果断处理解决。展昭,你负责给王朝马汉出题,让他俩来解决。
得令!
展昭
展昭冲王朝马汉一挑眉,开始一顿操作猛如虎,王朝马汉则在一旁密切关注着数据库集群环境的状态。
(一盏茶后)
王朝
大人,不好啦!集群现在很多会话出现Waiting for table metadata lock,活跃会话数一直在增长。

包拯初问
包拯
莫慌,看现象只在一个节点上有锁等待,当前集群全局元数据锁有哪些?
现在集群有一个DDL在执行,test.sbtest1表正在创建索引,应该是DDL阻塞了其他的DML操作。
王朝

马汉
不对呀,大人,您刚才不是说集群已经支持ONLINE DDL了吗?
包拯深思
包拯
别急着下结论,查询一下此表有关的DML会话状况,按时间排序展示。
大人,发现有一条慢SQL发生在此DDL操作前,且DDL语句状态是preparing alter table。
王朝

包拯捋了捋胡子、点点头,露出意料之中的神情。
包拯
去DN上查询此表的会话情况。
请看,DN上未发现创建索引的会话,但有一条LOCK TABLE会话信息。在此会话前,有一条sbtest1表相关的慢SQL。
王朝

包拯再问
包拯
你们觉得,这时最快的解决方法是什么?
我觉得应该KILL慢SQL,让DDL执行下去。
王朝
马汉
我认为应该在SN上KILL 掉创建索引的会话。
(摇了摇头)非也非也,别忘了自己的身份,我们是DBA,不能擅自做主KILL 业务SQL,而DDL失败了是可以重复执行的。
包拯
现在,SN已经向DN发送了LOCK TABLE指令,在SN上KILL会话已不是最佳时机。此时,最快的处理方式是KILL DN上LOCK TABLE的会话,让业务顺利进行,然后再跟应用小伙伴们讨论慢SQL是否需要KILL及优化的问题,告诉他们该慢SQL影响了DDL的执行,我们已终止了DDL会话,DDL不能与慢SQL同时执行。
(王朝马汉点点头,内心OS:大人高见。)
王朝
明白了大人,我立即处理DN上锁表的会话。
展昭听到此,露出一个意味不明的微笑,又啪啪啪操作了几下。
(片刻之后)
报错信息:集群又出现了Waiting for table metadata lock状态的大量会话,而且这次两个SN节点会话都受到影响,看来展大哥出组合拳了。但查看集群元数据锁,看到还是只有一个创建索引的DDL语句,也查看了DN上的会话,发现DDL会话状态为Waiting for table metadata lock,有一个慢SQL的执行耗时比DDL会话少13秒。



包拯沉思
包拯
当前集群会话中,是否有其他DDL操作?
除了创建索引的DDL外,又出现了两条创建触发器的会话。这两个会话发生在不同的SN节点上,而user属于内部用户system user。
王朝

包拯
用户是system user,说明是集群内部操作,这个会话动不得。这次业务慢SQL保不住了,把慢SQL语句记录下来,KILL掉慢SQL会话,同时在DN上KILL掉创建索引会话。
是,大人,我马上处理 。
王朝
马汉
大人英明,集群会话恢复正常了。
展护卫,我猜你刚才的操作是这样的:
包拯
第一次,用一个SN先发出一个慢SQL,然后在另一个SN上使用慢SQL相关的一个表,在上面创建索引。
第二次,用一个SN先发出创建索引命令,间隔13秒后在另一个SN上,在索引创建完成前发出了此表相关的一个慢SQL,继而又换了一个SN,发出一个创建触发器的指令。对与不对?
展昭
大人神算!但属下有两点不解,请您赐教:第一次操作中,您如何知道我换了一个SN创建索引,如果我仍连接相同的SN,在上面创建索引,处理方式会不同吗?
如果你创建索引与执行慢SQL连接相同的SN,在SN中会被拦截,SN会话状态将是Waiting for table metadata lock,而非Preparing alter table。DN上不会接收到LOCK TABLE的指令,此时在SN上KILL 创建索引的会话即可。
包拯
展昭
(点点头,恍然大悟)第二点,您如何知道我第二次操作连接了三个SN?
(会心一笑)是你创建的触发器露出了马脚,分别在两个节点上出现system user执行的创建触发器的会话,说明这两个节点在回放过程中都受到了阻塞,分别在等待慢SQL与创建索引的会话结束,所以我才说慢SQL与创建索引的操作都保不住了。因为不能动system user会话,动之会让SN节点状态变为ERROR,为了集群的稳定,只能牺牲慢SQL与创建索引的操作。
包拯
展昭+王朝+马汉
(齐声道)大人就是大人,我等佩服。
别拍马屁了,展护卫做一下本次故障演练的总结吧。
包拯
展昭总结
1.慢SQL判断:集群支持在线创建索引,但开头和结尾需短暂获取两次元数据锁,慢SQL会对其造成阻碍,这个慢SQL有可能发生在创建索引之前,也有可能发生在创建索引过程中。要根据SN和DN的会话状态判断创建索引执行到哪一步,不同的步骤要采取不同的处理方式。
2.开发运维小伙伴不按套路出牌时:要尽快定位问题,尽己所能减少此类问题造成的伤害。因此,我们要了解数据库的原理与行为表现,遇到问题时,冷静果断地进行分析定位,该出手时立即出手。
3.最重要的一点:天下武功,唯快不破,数据库出问题,大多出在慢SQL上。因此,我们要经常对慢日志进行分析,发现慢SQL,对其优化。无论选择什么方式,或以空间换时间,或以并发资源换时间,总之要保证其能快速执行,才能避免数据库集群出问题。
故障寄语
出现故障并不可怕,可怕的是我们没有任何解决思路。如果这篇文章没有帮到你,请关注《包拯断案》专栏,期待下篇文章给你带来更多精彩干货。












