故障背景
某公司进行一年一度的跨年上线工作,在2018年的12月30号上午忽然接到保障业务无法运行,而且影响全国业务。
故障分析
第一步:因为近期没有业务上线活动,首先排除因上线因此引起的故障
。
第二步:分析业务日志。发现业务中报错的原因是没有查到业务表中前期存的业务数据
。
第三步:查询前期存表操作,查找是什么原因导致业务数据没有存到数据库中
。然后发现业务中并没有抛出任何存表异常(这是一个坑,笔者也跳进去了饶了好几次才发现)。此处解释一下:因为业务数据量比较大,因此业务上采取的是分年月的分表规则进行业务信息存储
,同时此时属于跨年的时间节点,业务上一般会提前一周将下一年的表结构刷入数据库中。
第四步:故障定位。上面的数据库确实没报错,然后通过显示mybatis中sql语句
方式,看到sql入的表是T_BUSI_201912的表,也就是说本来如表应该是T_BUSI_201812的表现在存到表T_BUSI_201912
,很明显,这里的分表日期计算错了。因为T_BUSI_201912表结果已经提前刷入生产环境,因此没有出现入库异常。
故障重现
根据上面的分析,我们找到了错误的原因开发者使用的是YYYYMMdd
格式化当前日期。那现在就用测试代码重现一下当时的故障。测试代码如下所示:
/**
* 故障重现
*/
public static void troubleReproduce() throws ParseException {
//业务中使用的日期格式化方式
String formate1 = "YYYYMMdd";
//比较格式化方式
String formate2 = "yyyyMMdd";
//这个是故障发生的时间
String dateTime = "20181230";
//这个是故障发生前一天的时间
String dateTimeTest = "20181229";
//这个是将字符串转换成时间
Date date = new SimpleDateFormat(formate2).parse(dateTime);
Date dateTest = new SimpleDateFormat(formate2).parse(dateTimeTest);
System.out.println("使用[" + formate1 + "]格式化前后{"+dateTime+"} -> " + (new SimpleDateFormat(formate1).format(date)));
System.out.println("使用[" + formate2 + "]格式化前后{"+dateTime+"} -> " + (new SimpleDateFormat(formate2).format(date)));
System.out.println("-----------------分割线---------------------");
System.out.println("使用[" + formate1 + "]格式化前后{"+dateTimeTest+"} -> " + (new SimpleDateFormat(formate1).format(dateTest)));
System.out.println("使用[" + formate2 + "]格式化前后{"+dateTimeTest+"} -> " + (new SimpleDateFormat(formate2).format(dateTest)));
}
打印结果如下:
使用[YYYYMMdd]格式化前后{20181230} -> 20191230
使用[yyyyMMdd]格式化前后{20181230} -> 20181230
-----------------分割线---------------------
使用[YYYYMMdd]格式化前后{20181229} -> 20181229
使用[yyyyMMdd]格式化前后{20181229} -> 20181229
这个例子就重现了案发现场,如果是2018年12月29号的时候系统都能正常运行,到了2018年12月30号的时候系统就无法正常运行了,应该存T_BUSI_201812表的数据错误的存入T_BUSI_201912中。
解释总结
上面成功找到了问题的原因,那我们要刨根问题为什么YYYYMMdd和yyyyMMdd得到的结果是不一样的,为什么YYYYMMdd出现的结果是不对的?
因为YYYY是week-based-year,表示当天所在的周属于的年份,2018年的12月30号是周日,周日在西方人认为是一周的第一天,因此本周存在跨年(2019年),所以就算入下一个年份中了。 但是2018年12月29号是本周的最后一天,这一周都在2018年,因此显示是正常的。
所以这一点程序员要谨记,尽量不要使用YYYY这样的年份规则。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72731.html