7月19日,话题“微软蓝屏”冲上了热搜榜第一。微软公司旗下部分应用和服务出现访问延迟、功能不全或无法访问问题,大量用户端电脑出现蓝屏现象。这个技术故障席卷全球,短短两个小时,就造成一场令人措手不及的大规模事件:多个国家和地区航班停飞,医疗、银行、酒店等行业“停摆”,连伦敦股票交易所都受到波及……微软很快就查明事故的根因并及时处理,此次故障与一家与微软有关联的全球安全公司CrowdStrike有关,因为推送了一个“更新”,却触发了某些Windows的bug导致了系统蓝屏。
重视代码质量,不断优化质量控制机制,才能保证系统的安全性和稳定性。数据库层面如果出现这种失误也必将会造成巨大影响,那么该如何避免呢?
功能上线前SQL质量把控的必要性
在功能上线前,开发者通常需要进行SQL变更。这些SQL语句,在上线前很难识别是否存在潜在的坑和性能问题,发布后一旦出现错误,可能会导致数据丢失、性能下降甚至系统崩溃,对业务产生严重影响。因此在上线前进行SQL审核是非常有必要的,下面我们通过一个简单的例子来详细说明。
表结构和业务代码简化如下:
create table user_login_history (
`user_id` varchar(32) NOT NULL PRIMARY KEY COMMENT '用户id',
`login_time` int(11) NOT NULL DEFAULT 0 COMMENT '登录时间',
`login_status` varchar(32) NOT NULL DEFAULT '' COMMENT '登录状态:success|failed',
`failure_reason` VARCHAR(255) DEFAULT '' COMMENT '登录失败原因'
);
业务代码中涉及到如下相关SQL语句:
// 插入登录历史
stmt, err :=conn.Prepare("insert into user_login_history values(?,?,?,?)")
if err != nil {
log.Logger.Errorf("prepare sql failed")
return err
}
// 定期清理历史表
sql := fmt.Sprintf("delete from user_login_history where
login_time<unix_timestamp(now())-%d limit 100", timeBefore)
for {
_, err := conn.Exec(sql)
if err != nil {
log.Logger.Errorf("DelLogInHistory exec sql failed, sql:%s, err:%v", sql, err)
}
time.Sleep(10 * time.Second)
}
上面SQL存在哪些问题?
从上面的代码中可以看到有以下两个问题:
1)代码中插入user_login_history表没有指定列名,新功能版本需要对该表进行新增字段,采用以下两种发布方式,会出现什么结果?
-
方式一:先发布该表新增字段的SQL,然后滚动升级应用。
-
方式二:先修改原有的版本将user_login_history表进行指定列名insert,然后滚动升级,升级完成后再发布新版本,先发布该表新增字段的SQL,然后滚动升级应用。
很多小伙伴是不是也会选择方式一进行发布,如果你真这么做了,那么一次故障review少不了。从执行新增字段SQL开始,滚动升级这段时间,老版本服务insert into user_login_history将会失败(由于新增的字段老版本服务代码中没有指明对应的value,字段个数对不上)。
选择方式二的小伙伴也许曾经踩到过类似坑吧,第一次服务滚动发布修复insert表未指定列问题,第二次服务滚动发布进行新功能发布。
2)历史表数据量一般都比较大,需要定期按照时间进行清理。从上面代码看user_login_history的login_time字段未添加索引,如果该表数据量增长迅猛或清理任务堆积,那么也会存在问题。
-
系统刚上线时用户量比较少,并且只保留7天内的登录历史,没出现性能瓶颈,但是随着业务的增长,7天内的登录量超过几十万甚至几百万,那么清理的SQL将变慢。
-
当SQL变慢,清理的任务会存在delay或者积压,会导致单条SQL扫描的页越来越多,甚至引起磁盘IO打满。一旦IO打满那么灾难就来了,应用服务重启也没用,只要有清理任务调度基本就挂。
清理任务涉及的login_time字段没加索引全表扫描,导致磁盘IO异常,从而会影响业务稳定性。
为什么会出现这么低级的问题呢?
对于开发同学来说,由于日常开发任务紧,一些类似insert不指定列的问题没有足够重视,先完成功能(不指定字段代码写起来比较省事),往往就会引入此类问题。不加索引导致故障的问题数不胜数,刚开始业务量比较小,表中数据不多,就算没索引也不会存在问题,缺乏对业务未来的评估。
通过这个例子也能看出依赖人工进行SQL审核和代码Review并不能完全识别出潜在问题。比如以下场景:
-
DBA或者SE比较忙没时间进行仔细的SQL审核
-
有些公司也没有专职DBA,
-
SQL质量全靠开发自己负责。
人工Review的方式不靠谱,那么有没有好的工具能识别出类似上述问题呢?
DBdoctor自动批量SQL审核(规范审核+性能审核)防止“蓝屏事件”发生
行业内SQL审核的工具比较多,但大多数都聚焦在规范审核上,缺少针对SQL性能的审核。近期DBdoctor发布了批量性能审核的功能,开发人员可以快速发现并解决SQL语句中的各种问题,大大提升SQL质量和系统的稳定性。
-
提升审核效率:支持SQL窗口输入和上传SQL文件两种方式,自动化的批量审核大幅减少了手动审核的时间和工作量,极大地提高了审核效率。
-
统一审核标准:系统化的审核规则确保了SQL语句审核的一致性和准确性,避免了人工审核的主观差异。
-
提前性能审核:行业独有的外置Cost优化器,无需任何变更,开发阶段即可评估该SQL未来上线后的性能,自动推荐最优索引,提前解决性能问题。
-
降低人工成本:减少了对高技能审核人员的依赖,降低了SQL审核的整体成本。
-
优化数据库性能:通过全面的性能优化建议,确保数据库运行在最佳状态,提升应用程序的响应速度。
-
实时反馈:审核结果实时生成,便于开发者快速定位问题并进行修正。
如何用DBdoctor进行批量SQL审核
1.上传DDL文件
将此次版本涉及到的DDL文件上传。
2.查看任务详情
任务详情中分别展示每条SQL的审核结果。
3.查看审核详情
审核结果中对性能审核结果和规则审核结果分别展示。
4.同样的步骤审核DML文件
可以看到插入语句未显示指定列名插入,当表中存在1000条数据时,加上索引性能提升543倍,并提示出添加索引的SQL语句。
结语
在当今数字化的时代,数据库的稳定和高效运行对于各行各业来说都是至关重要的。SQL语句作为数据库操作的基石,其质量和性能直接关系到整个系统的稳定性和安全性。然而,面对海量SQL语句的审核需求,传统的人工审核方式早就不能满足效率及准确率的需求。DBdoctor作为一个先进的数据库性能诊断和优化平台,提供的批量SQL审核功能,可帮助开发者和数据库管理员在多场景下对SQL语句进行高效、准确的审核,有效避免潜在事故的发生!
1️⃣ 产品介绍:
DBdoctor产品介绍
2️⃣免费下载/在线试用:
https://dbdoctor.hisensecloud.com/col.jsp?id=126