数据库十宗罪01-查询引发宕机!

说明:

数据库中查询相关的BUG并不少见,例如Oracle早期版本的Cardinality feedback、BITMAP CONVERSION等功能不稳定,有时会严重影响查询性能,除了打补丁或升级版本以外,还可以通过设置隐含参数禁用相关不稳定的功能,跳过此问题。

这也是Oracle数据库比较高明的一个地方,新功能基本上都会有一个手动关闭的接口,可以在解决问题的同时最小化减少对业务的影响决,这里并不是在对Oracle无脑吹,评判一个数据库产品功能、代码是否足够健壮,很多时候就是通过这些不起眼的细节处分出高下的。

近期发现多起查询引发BUG的问题,这次的BUG比较严重,查询语句直接引起数据库宕机,并且没有类似Oracle的隐含参数功能,只能通过升级解决

此类问题定义为"数据库的十宗罪之一"并不为过,很常见的查询操作,因为BUG直接导致数据库宕机,而且解决方式影响也比较大,只能通过升级数据库解决。

其中一个是某国产数据库,另一个是MySQL数据库。

国产数据库先不多说了,厂商定位及解决问题还算及时,最后升级数据库解决了此问题。

今天主要说下MySQL数据库因为BUG导致查询引发的宕机问题。

问题现象:

DB:MySQL 8.0.24

查询如下语句:

SELECT GROUP_CONCAT(b.id) chen_data_id,

这里先不讨论SQL写的烂不烂,再烂也不是宕机的理由。

就算数据库是这样设计的:

客户也可能是这样使用的:

没毛病,客户永远都是对的。

上面的查询引起MySQL数据库自动宕机,前台信息如下:

mysql> use cjc

error日志信息如下:

05:47:34 UTC - mysqld got signal 11 ;

问题分析:

通过gdp查找具体代码位置为sql_parse.cc:1841

继续检查sql_parse.cc:1841位置代码,没有分析出有效信息

既然出问题的是8.0.24版本,那么8.0.25版本修复的BUG中能否有相似的问题?

https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-25.html

果然看到了相似度极高的BUG

描述如下:

For a prepared, implicitly grouped SELECT statement in which the WHERE clause was determined always to be false, the result of some aggregate functions could sometimes be picked up from the previous execution of the statement. (Bug #103192, Bug #32717969)

翻译为中文:

对于已准备好的、隐式分组的SELECT语句(其中WHERE子句被确定为始终为false),某些聚合函数的结果有时可以从该语句的前一次执行中提取。(Bug #103192, Bug #32717969)

解决方案:

也咨询了原厂,答复如下:

数据库实例的crash是由于下面的bug导致的:

Bug 32717969 - WRONG RESULT OF EXECUTE PREPARE ON 'SMALLINT'

其关联bug是:

Bug 32801496 - MYSQL 8.0.24 CRASHES WHEN QUERY USES GROUP_CONCAT(DISTINCT WITH EMPTY RESULT SET

上述bug已经在 8.0.25 版本中修复,因此解决方法就是升级到 8.0.25 以上,建议用户升级到目前最新的GA版 MySQL 8.0.36,以规避更多Bug的影响,增加稳定性,同时获得更多增强的功能特性。

经过测试,此问题在8.0.24版本可以稳定重现,升级到8.0.3x版本可以解决此问题,很遗憾,此问题并不能通过修改某个参数临时解决。

相似问题:

之前看过微信公众号号“爱可生开源社区”发布过的一篇文章,标题是《故障分析 | 一条 SELECT 语句跑崩了 MySQL ,怎么回事?》,原文连接如下:

https://mp.weixin.qq.com/s/c3I6uy8g4bVQGa9KYRZHww

最开始以为是同一个问题,但仔细看是两个问题,这个问题的数据库版本似乎是8.0.19,也是某类查询触发BUG导致实例宕机。

通过原文可以看到,触发宕机的语句如下:

SELECT DISTINCT T.CUST_NO

宕机时error.log日志如下:

Trying to get some variables.

分析详细过程请通过上面的链接查看原文。
这个案例的解决方案如下,可以通过修改参数临时解决此问题,原文如下:

在上述排查分析中,我们得到这个 bug 是由于使用了 semi-join 的 DuplicateWeedout 执行策略导致了问题的发生,如果在短时间内无法升级变更数据库,而又想尽量避免这个问题的发生。

一方面肯定是业务侧避免该 SQL 的执行,从 DBA 的角度上考虑的是该 SQL 怎样才能正常执行,那么经过验证:

以下三种解决方案均可解决当前 select 查询导致的数据库崩溃问题。

1、业务表设置合理统一的字符集(utf8mb4)和排序规则,避免 exist 在半连接中使用了DuplicateWeedout 策略,加快 SQL 执行效率;

2、关闭数据库级别的 DuplicateWeedout 优化策略:

SET [GLOBAL|SESSION] optimizer_switch='duplicateweedout=off';

3、升级 MySQL 版本到 8.0.24 ;

结束语:

数据库升级需谨慎;

上面第二个案例讲到,8.0.19的这个严重BUG,已经在8.0.24版本修复了,但也不建议直接升级到8.0.24版本,个人认为修改参数解决是最稳妥的,屏蔽的功能也不是必须要使用,但如果就是要升级到8.0.24,也需要提前知道升级到8.0.24版本会遇到哪些新的BUG,数据库升级是一个比较大的变更,需要充分评估必要性和风险,例如第一个案例里讲到的BUG就是8.0.24特有的,如果不做这些准备工作,你会发现,当你终于搞定了一个BUG!然后发现出现了更多BUG。


欢迎关注我的公众号《IT小Chen

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值