非常抱歉,这次故障给您带来麻烦了,请您谅解。

今天早上 10:54 左右,我们所使用的数据库服务(阿里云 RDS 实例 SQL Server 2016 标准版)CPU 突然飙升至 90% 以上,应用日志中出现大量数据库查询超时的错误。

Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
---> System.ComponentModel.Win32Exception (258): Unknown error 258

我们收到告警通知并确认问题后,在 11:06 启动了阿里云 RDS 的主备切换, 11:08 完成切换,数据库 CPU 恢复正常。但是关键时候 docker swarm 总是雪上加霜,在数据库恢复正常后,部署博客站点的 docker swarm 集群有一个节点出现异常情况,部分请求会出现 50x 错误,将这个异常节点退出集群并启动新的节点后在 11:15 左右才恢复正常。

通过阿里云 RDS 控制台的 CloudDBA 发现了 CPU 近 100% 期间执行次数异常多的 SQL 语句。

SELECT TOP @__p_1 [b].[TagName] AS [Name], [b].[TagID] AS [Id], [b].[UseCount], [b].[BlogId]
FROM [blog_Tag] [b]
WHERE [b].[BlogId] = @__blogId_0
AND @__blogId_0 IS NOT NULL
AND [b].[UseCount] > ?
ORDER BY [b].[UseCount] DESC

上面的 SQL 语句是 EF Core 3.0 生成的,其中加粗的  IS NOT NULL  就是 EF Core 3.0 的一个臭名还没昭著的 bug —— 生成 SQL 语句时会生成额外的  IS NOT NULL  查询条件。

谁也没想到(连微软自己也没想到)这个看似无伤大雅的多此一举却存在致命隐患 —— 在某些情况下会让整个数据库服务器 CPU 持续 100% (或者近 100%)。一开始遇到这个问题时,我们也没想到,还因此错怪了阿里云(博文链接),后来在阿里云数据库专家分析了我们遇到的问题后才发现原来罪魁祸首是 EF Core 生成的多余的 "IS NOT NULL" ,它会在某些情况下会造成 SQL Server 缓存了性能极其低下(很耗CPU)的执行计划,然后后续的查询都走这个执行计划,CPU 就会居高不下。这个错误的执行计划有双重杀伤力,一边巨耗数据库 CPU ,一边造成对应的查询无法正常完成从而查询结果不能被缓存到 memcached ,于是针对这个执行计划的查询就越多,雪崩效应就发生了。唯一的解决方法就是清除这个错误的执行计划缓存,主备切换或者重启服务器只是清除执行计划缓存的一种简单粗暴的方法。

在我们开始遇到这个问题,就已经有人在 github 上反馈了这个问题:

Yeah this needs to be fixed asap. We just deployed code that uses 3.0 and had to immediately revert to 2.2 because simple queries blew up our SQL Azure CPU usage. Went from under 50% to 100% and stayed there until we rolled back.

但当时没有引起微软的足够重视,在我们知道错怪了阿里云实际是微软的问题之后,我们向微软 .NET 团队反馈了这个问题,这次得到了微软的重视,很快就修复了,但是是通过 .NET Core 3.0 Preview 版发布的,我们在非生产环境下验证了  IS NOT NULL 的确修复了,由于是 Preview 版,再加上 .NET Core 3.1 正式版年底前会发布,所以我们没有在生产环境中更新这个修复,只是将上次出现问题的复杂 SQL 语句改为用 Dapper 调用存储过程。后来阿里云数据库专家进一步对我们的数据库进行分析,连平时数据库 CPU 的毛刺(偶尔跑高的波动)都与  IS NOT NULL  有关。

这就是这次故障的背景,在我们等待 .NET Core 3.1 正式版修复这个 bug 的过程中又被坑了一次,与上次不同的是这次出现问题的 SQL 语句非常简单,而且只有一个 "IS NOT NULL" ,由此可见这个坑的杀伤力。

这个坑足以载入 .NET Core 的史册,另一个让我们记忆犹新的那次也让我们错怪阿里云的 .NET Core 坑是正式版的 .NET Core 中 SqlClient 竟然漏写了 Dispose ,详见 云计算之路-阿里云上:数据库连接数过万的真相,从阿里云RDS到微软.NET Core

【故障公告】数据库服务器 CPU 近 100% 引发的故障(源于 .NET Core 3.0 的一个 bug)的更多相关文章

  1. 【故障公告】数据库服务器 CPU 近 100% 引发的故障

    抱歉,今天上午 10:48 ~ 10:33 期间,我们所使用的数据库服务(阿里云 RDS 实例 SQL Server 2016 标准版)又出现了 CPU 近 100% 问题,由此给您带来麻烦,请您谅解 ...

  2. 关于【【故障公告】数据库服务器 CPU 近 100% 引发的故障(源于 .NET Core 3.0 的一个 bug)】IS NOT NULL测试

    测试如图,Core_Users的PhoneNumber可为空,存在索引,记录数1500000+ 增加is not null,查询计划消耗增加了一个0%的筛选器消耗,IO消耗如下一模一样 如果是IS N ...

  3. 【故障公告】阿里云 RDS 数据库突发 CPU 近 100% 引发全站故障

    今天晚上9点我们收到阿里云的告警通知: [阿里云监控]华东1(杭州)-云数据库RDS版<cnblogsdb> [instanceId=xxx] 于21:00 发生告警, 前往诊断 CPU使 ...

  4. 云上的芯脏病:奇怪的阿里云 RDS 数据库突发 CPU 近 100% 问题

    最近遇到了奇怪的阿里云 RDS 数据库突发 CPU 近 100% 问题,遇到了3次. 第一次是10月12日(周六)凌晨 3:24 负载极低的时候开始出现,早上发现后进行了主备切换,恢复了正常. 第二次 ...

  5. Oracle触发bug(cursor: mutex S),造成数据库服务器CPU接近100%

    问题现象: 项目反馈系统反应非常缓慢,数据库服务器CPU接近100%! INSERT INTO GSPAudit1712(ID,TypeID,CategoryID,DateTime,UserID,Us ...

  6. Oracle触发bug(cursor: mutex S),造成数据库服务器CPU接近100%---SQL子游标多版本问题

    问题现象: 项目反馈系统反应非常缓慢,数据库服务器CPU接近100%! INSERT INTO GSPAudit1712(ID,TypeID,CategoryID,DateTime,UserID,Us ...

  7. 【故障公告】K8s CofigMap 挂载问题引发网站故障

    今天凌晨我们用阿里云服务器自建的 kubernetes 集群出现突发异常情况,博客站点(blog-web)与博客 web api(blog-api)的 pod 无法正常启动(CrashLoopBack ...

  8. 阿里云 RDS 数据库又发 CPU 近 100% 的“芯脏病”

    最近云界发生了2件事,一件是大事,一件是小事,大事是阿里云与微软合作推出了开放应用模型 Open Application Model(OAM),小事是由于微软 SQL Server 在阿里云上水土不服 ...

  9. 【故障公告】数据库服务器 CPU 100% 引发全站故障

    今天 11:12-12:03 期间,园子使用的阿里云 RDS 实例(SQL Server2016 标准版,16核CPU)出现 CPU 100% 问题,引发全站故障,由此给您带来麻烦,请您谅解. 发现故 ...

随机推荐

  1. HDU 6607 Time To Get Up(状态压缩+枚举)

    题目网址: http://acm.hdu.edu.cn/showproblem.php?pid=6077 思路: 先预处理一下,将每个数字块的“X”看作1,“.”看作0,进行状态压缩转换成二进制数,用 ...

  2. Windows下Python虚拟环境的配置

    一.了解Python虚拟环境 所谓虚拟环境可以理解为不同的不连通的本地设备,打个比方就是在一台电脑上能做到多台电脑能做的事情. 例如:现在我们有两个项目需要不同的配置,记为A项目需要库a------- ...

  3. 图像配准SIFT

    (一)图像特征匹配--SIFT 1.1 SIFT背景简介 SIFT算法是David Lowe在1999年提出的局部特征描述子,并在2004年深入发展和完善. SIFT算法是在尺度空间进行特征检测并确定 ...

  4. 百万年薪python之路 -- 面向对象初始

    面向对象初始 1.1 面向过程编程vs函数式编程 函数编程较之面向过程编程最明显的两个特点: 1,减少代码的重用性. 2,增强代码的可读性. 1.2 函数式编程vs面向对象编程 面向对象编程:是一类相 ...

  5. 使用 pdf.js 跨域问题的处理方法1

    在<使用 pdf.js 在网页中加载 pdf 文件>中详细介绍了 pdf.js 的使用与集成网页开发的基本方法.展示效果如下图: 站点的目录为 http://localhost:8033/ ...

  6. Java设计模式之状态模式详解

    (本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...

  7. Markdown进阶(1)

    对于工科生来说,在书写Markdown文本时,免不了要和上下标打交道,网上的博客大多良莠不齐,不太友好,本文想尽可能地解决一些在看完基础教程后再来书写Markdown文本时容易遇到的问题. 1.上下标 ...

  8. 组合+封装+property+多态+鸭子类型(day21)

    目录 昨日回顾 继承 什么是继承 继承的目的 什么是抽象 继承背景下,对象属性的查找顺序 派生 什么是派生 子类派生出新的属性,重用父类的属性 新式类和经典类 钻石继承的继承顺序 今日内容 一.组合 ...

  9. SpringBoot与MybatisPlus3.X整合示例(十六)

    包含 分页.逻辑删除.自定义全局操作 等绝大部分常用功能的使用示例,相当于大整合的完整示例 pom.xml <dependencies> <dependency> <gr ...

  10. Mybaits 源码解析 (八)----- 全网最详细,没有之一:结果集 ResultSet 自动映射成实体类对象(上篇)

    上一篇文章我们已经将SQL发送到了数据库,并返回了ResultSet,接下来就是将结果集 ResultSet 自动映射成实体类对象.这样使用者就无需再手动操作结果集,并将数据填充到实体类对象中.这可大 ...