打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
沉痛的教训,SQL SERVER 2008 R2升级到SQL2012 SP1导致的系统全线崩溃

2014年07月23日01:00~05:00,公司的系统与往常一样,进行升级。但是这次更新,是比较大的改动,“大”在于系统新功能的添加,BUG的修复,以及一个我始料未及的SQL SERVER升级(事前,我不知道今晚会更新SQL SERVER)。光是程序的改动,是经过了45天左右的改动,然后决定今天发布的,改动的地方有100+。

正是因为这一系列的问题,导致了“看似偶然,实则必然”的系统全线崩溃。本文并非来说谁对谁错,仅仅是针对这次的教训,要狠狠的记住它!

沉痛的教训,SQL SERVER 2008 R2升级到SQL2012 SP1导致的系统全线崩溃

这次的灾难,可以说是本人所经历过最沉重的、最具毁灭性的灾难。本人从事.NET软件开发3年以来,第一次遇到这么大的灾难性故障,最终造成公司300+分店,几千个客户端系统,19.5小时的全部瘫痪,一直到20:30才“无奈的解决”(被迫降级,全部回滚旧版本)。

虽然本人没有参与本次系统更新,但是作为一个小组团队,我也是除了经理以外的唯一一个开发人员(我们这个小组有2人(还有几个其他的开发小组),此外,最近新来了1人,这次更新部分代码他也参与改动),我有着难辞其咎的责任。因为,我没有提前发现问题,没有给出合理的建议,导致问题出现了。问题出现之后,我也没有尽快把问题解决,中间走了很多弯路,导致故障很晚才被修复,经理,以及其他管理层,因为这件事情全都被扣了5K工资,我也是非常不安,实在是沉痛的教训!

今天经历的事情(或者是背景说明):

1、本次系统更新改动很大,测试工作不到位。虽然所有功能都经过测试,但是没有模拟足够大的并发,也没法模拟“真实”的环境,导致问题一直无法发现。(因为在测试版运行了2个多月,一直正常)

2、公司也为了节约成本,测试服务器配置,完全跟正式服务器不同。这也就导致后面的SQL SERVER出了大问题;

3、SQL2008 R2升级为SQL2012 SP1,导致本人之前提供更新的文件配置,全部不对了(例如:里面的SQL地址连接,账号密码等,全都没用了。而且,由于更新的系统很多个版本,共有5个版本)。虽然,参与更新的同事换成SQL2012之后,也修改了这些配置,但是残留了一个Log4net.config,忘记修改它的连接,于是乎,导致系统死机的第一个原因产生了。

4、SQL2008 R2升级到SQL2012 SP1,谁知道2012企业版还有Licensed限制,通过CAL方式注册的(也就是大家网上搜索的那种验证码注册),会有CPU线程数限制,不能超过40个(详情这里)。但是我们的正式服务器是4*12=48个逻辑CPU,超出了8个,这样的话,就会导致之前的跨NUMA问题。关于这个问题,看这个文章:《SQL2008 R2 分库后出现“查询处理器未能为执行并行查询启动必要的线程资源”解决方法》。还有另一种Core方式注册的(正版购买的SQL2012企业版),是不会有这个限制的。正是因为正式服务器,测试服务器这个微妙的差异,所以这个问题被忽视了,公司也没有DBA,于是导致了毁灭性的灾难,所有的系统,完全卡死……重新建立索引,更新统计信息,重新设置最大并行度,全部没用。

5、其实,我们尝试了各种方法,一开始的时候,我们就在分析程序原因。但是整个早上都没有找到原因。下午的时候,才把目标转向SQL SERVER 2012。一开始的时候,我们就想回滚整个程序、数据库,但是SQL2008升级到SQL2012,是通过分离,附加的方式加上去的,根本不可能降级了。而且新版本,老版本的数据库结构有一些差异,而且过了这么久,2012上面的系统数据肯定多了很多账务,想要通过之前的备份还原也是不可能了。这就导致,我们没有及时回滚程序、数据库。而是一心想要找到原因,把问题解决……其实,现在想起来,这个做法是严重错误的。因为正确的方法是:立刻还原,回滚。而不是找原因,因为所有分店系统全部崩溃了……

6、挣扎了很久,直到下午,我突然想起那个“万能的数据库导入、导出”,于是建议经理通过这个方式,把2012的数据,全部弄回去。操作过程中,我们发现“数据库复制”速度更快些,而且整个库复制,比较方便。就这样,我们把SQL2012的数据成功的降级到SQL2008 R2。详细操作:通过SQL导入导出方式,把SQL2012降级为SQL2008(用之前的SQL2008备份,附加回2008,然后TRUNCATE TABLE XXX,再把2012数据导入)。也可以用SQL的复制功能(任务–复制数据库)实现相同的效果。……然而这个“新技能”的代价就是5K,4个管理层都扣了,那就是2W……

7、原以为到了这里,问题就可以解决了……可是,仅仅是比之前的卡死好了一点,但依然很卡。还没有从根本上解决这个问题……反正都把数据库还原了,就干脆把程序一起还原吧,还原之后,发现确实不卡了。使用新版本的程序,SQL某个数据库的连接数居然有400+,但是旧版代码只有几十个……看来,除了上面的问题,还有代码问题。估计是某些地方没有释放连接……

8、截止到现在,系统已经恢复工作了,其实,中间发生了很多很多其他的故障。本文没法一一举例了,就说这些比较重要的吧。目前关于代码的这个问题,我们还没有找到原因,明天会跟进严查。看看是什么原因导致的……说到这里,标题可能有点跑偏了,应该是“程序+SQL2012,导致系统全线崩溃”!之所以写这个标题,是因为让我记住,SQL不是每个人都能玩得起的……

9、经过这次事故,公司决定成立相关的应急方案,以及提供可靠的灾备服务器。(其实,原本是有灾备服务器,也有历史备份库的,但是上周这个机子发神经,同步中断了,系统也出问题了。昨天刚刚好被运维重装系统了,现在都是裸机一枚……真心伤不起)

最后,我想大吼一声:DBA,你在哪里?

============================2014年7月27日更新补充============================

前几天坑爹问题,罪魁祸首,应该找到了……(暂未最终确认,但应该就是它导致的)

这个写法,在不同版本的EF里面,实现方式不同,导致我们公司23号,所有系统全线崩溃……详细背景:http://www.wuleba.com/?p=25767

EF6.0,EF6.1 调用都是上面的代码……但是SQL连接数 6.1会增加25个连接(3~5秒关闭),EF6.0的话仅有1个连接(瞬间关闭,现在改为Contains方法查询,一次解决)……

后果是:2000个客户端 ,每隔3分钟调用1次,每次25个连接……数据库服务器CPU100%,所有系统全部崩溃……

2,000 * 20 * 25 = 1000,000 次/小时

============================2014年7月28日更新补充============================

目前找到的主要原因,是因为:

EF6.1.1在处理WithRequiredPrincipal映射跟EF6.0处理方式不同,导致升级到EF6.1.1之后,每次的查询的SQL连接会增加25个,需要等到3~5秒才会自动关闭。。。而EF6.0里面只会有1个连接,立即关闭。。。我们测试了EF6.1、EF6.0.XXX都发现处理结果相同,但是EF6.1.1是有问题的。。。。保险起见,现在改回原来的EF6.0.0-alpha3版本

测试的时候发现EF6.1虽然生成的语句跟EF6.0的一样,但是他依然会增加25个连接,关闭也没那么快。(之所以产生这个问题,涉及到两个概念:“EF 双向一对一关系”、“EF 单向一对一关系”)

============================2014年8月13日更新补充============================

上面是微软官方针对EF6.1.1一对一关系查询语句bug的回复邮件,该bug在EF6.1.2修复,目前6.1.2还是试用版。

本文采用 CC协议 发布,转载请注明:转载自

乐吧软件站

本文链接地址:http://www.wuleba.com/?p=25767


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【分享】如何确定SQL SERVER 2000数据库已安装SP4补丁
一个SqlServer数据恢复实例案例
同时安装sql2000和sql2005
建立数据库链路链接
用SQL语句完成SQL Server数据库的修复
当SQL Server数据库崩溃时如何恢复
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服