文章目录

线上问题无大小,只要有隐患,出现了就是大问题。细节就是魔鬼。

细节就是魔鬼,今天真实的体验了一次什么叫做惊弓之鸟。

新上的需求今天开始放量,从放量开始的半小时左右开始出现大量的告警,这是很不寻常的。查看ELK告警信息,发现是sql-parser异常。我很惊讶,按道理这种问题是不应该出现的,但是线上问题无小事。

于是截取了一段日志如下,(消除了敏感信息)

Caused by: java.util.concurrent.ExecutionException: com.xxxx.sql.parser.SQLParserException: syntax error, expect RPAREN, actual IDENTIFIER url
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.alipay.zdal.parser.DefaultSQLParser.getStatement(DefaultSQLParser.java:177)
... 68 more
Caused by: com.xxxx.sql.parser.SQLParserException: syntax error, expect RPAREN, actual IDENTIFIER url
at com.alipay.zdal.parser.sql.parser.SQLParser.accept(SQLParser.java:136)
at com.alipay.zdal.parser.sql.dialect.mysql.parser.MySqlStatementParser.parseInsert(MySqlStatementParser.java:1774)

异常堆栈很清晰的指出问题所在:url字段处存在sql异常。

于是我找到这个版本的代码中该功能执行的sql,如下:(sql字段已经脱敏)

INSERT INTO table (
        aaaa,
        bbbb,
        cccc,
        dddd
        <isNotEmpty property="uid">
            ,uid
        </isNotEmpty>
        <isNotEmpty property="nickname">
            ,nickname,
        </isNotEmpty>
        <isNotEmpty property="url">
            url
        </isNotEmpty>
        ,userid,

好了,问题找到了,下面这行的值没有传递,导致sql解析器解析到逗号的缺失。实际运行的sql变成了

INSERT INTO table (
        aaaa,
        bbbb,
        cccc,
        dddd,
        uid url,
        userid,

这样sql解析就出错了。

所幸没有出现大问题,但是还是给各位同事带来了麻烦,让大家又额外的经历一次上线的流程。

总的来说,还是个人的原因导致的,不需要找客观原因。核心就在于,开发阶段测试用例覆盖率没有做好,非空判断依赖了数据库的动态SQL。

发现问题就要解决,及时止损,解决完问题要时刻反思进步。今天的事情给我的启示是:

  1. 上线前打TAG,对于上线完成的分支要做到留存,合并到主干后,待主干回归完成再删除。
  2. 开发阶段测试用例尽量覆盖到,这个我也做的不够好,只关注了正常的情况,对于边缘的情况一定要尽量覆盖到。对于测试同学提出的bug要及时跟进。
  3. 不要相信代码评审的结果,也就是不要相信他人,可以参考他人的意见,一切以测试用例执行情况为准。
  4. 对于sql而言,不要依赖sql本身的非空判断,出现问题不好复现,而且一旦出现线上问题,大多数人都不会太冷静,你更不会。对于空值的处理尽量在业务逻辑处理。

时刻牢记,细节就是魔鬼,线上问题无小事。

文章目录
Fork me on GitHub