背景
最近几天现场老反馈某个院的采集任务失败了,报错原因基本都是连接断开,关键是连续好几天,都是同一个地区出问题,这就很尴尬了。拉着好几个研发团队负责人一起讨论了一下,准备收集近期的运行情况及日志,深入分析一下根因,并规划后续解决方案。但也不能影响测试呀(本来定的本月完整集成测试的复测,且达到通过的标准的),然后让现场重新跑了一下采集任务,但是…依然是那个地区失败,依然是超时,但人家现场用工具操作好好地,一丁点儿的问题都没有!!!后来好歹各种折腾解决了,发片帖子分享下,给其他同学排查类似问题提供个新的思路。
过程
问题现象
连续几天晚上采集报错连接超时,且每天都是且仅同一个地区超时,其他地区都好好地,错误信息如下
初步思路
看到这个错误,总感觉是现场环境问题,让现场去验证网络是否稳定,服务器资源是否正常,然而并没有发现什么问题。同步的跟采集工具的负责人商量这种异常情况是否可以在工具层面规避?是否试验一下数据库连接池参数,或者增加重试机制等手段来尽量避免定时任务的失败(第一步采集失败会影响后面一整串的ETL流程,然后会导致第二天整天的数据都是不可用的,近期发病率还挺高,感觉都有1个9了)。
然后现场反馈执行失败的那个脚本,手工执行返回结果也很慢,我们一度怀疑是慢sql导致的,因为整个错误日志就那么两三处任务,基本都固定涉及到那两张表的操作(甚至还一通怀疑是否表锁导致的,或者现场部署了autokill工具自动杀掉进程了,各种猜测),还准备第二天看一下执行计划,确认是否慢sql导致的这个问题。
但今天又复现该问题的时候,人家现场还专门用工具连了一下数据库,操作都是正常的,就是采集失败,这特么就不科学了!还好,凡事儿都有两面,虽然超出了我们原来的猜想范围,但现在好歹能稳定复现,就比较好定位问题了。
问题定位
首先是我们跟现场要到了采集工具和sybase的日志,一通看,没啥卵用,还是看不出问题在哪儿。
但,突然现场问我们:采集的sql怎么修改?我把其中注释掉的那些字段都删除了,再执行就可以了(采集脚本里面有些使用–注释掉的字段,大概是为了后续好恢复吧,咱也不知道,咱也不敢问)。
我们还在讨论删除那个为啥会影响脚本执行呢?不可能呀,语法解析器肯定会滤掉这些注释的呀等等这些信息的时候,现场答复:搞定了,失败的那个地区采集成功了。
他成功了!他竟然成功了!不科学呀,他怎么会成功的?
定位根因
既然人家现场都搞到这个程度了,我们就顺坡下驴(没错,内头驴说的就是我们),继续研究吧。
脚本最前面的注释删掉?没啥作用。每行开头的注释删掉?没啥作用。超级长的注释删掉?没啥作用。注释全删掉?咦,他好了!!!
但这明显不对呀,语法解析器肯定是支持注释的呀,我们就不信邪,偏偏要加注释,然后就加了两行注释,依然正常!咦?再加几行,还是好用。
后来找各种sybase大拿沟通,说有个network参数看看是否有关,又一通试,最后折腾到可能跟命令长度有关。我们就开始逐步增加行数,从几十行增加到375行左右,果然报错了,那么他到底是限制行呢?还是限制命令总字节大小呢?简单,我们找到一个最近能执行的最大行数,然后给某个列增加别名就好了嘛,每次增加三五个,增加了几次,报错了。那么这就定位到了,这个超时的根因,是因为sybase限制了单个命令的最大字节数。
解决问题
但是哪个配置限制的呢?阈值又是多少呢?各种找人,各种谷歌,各种挖空脑细胞的想,也没找到一个解决办法。
既然没啥思路,那就瞎猫碰死耗子吧。同样的脚本,有的地区可以,有的地区不可以,且现在已经知道了根因是命令超过了sybase单个进程(连接、请求)最大字节数的阈值
,那么就想办法找是否有相似的配置吧,左右各开一个窗口,执行sp_configure命令,逐行看,逐行猜。
你还别说,在几百个配置里面,大海捞针,还真就捞到了那么几个疑似配置,逐个配置的去网上查最后筛选还剩俩配置stack size
和stack guard size
,就这俩看着还像点儿,且确实是出错的地区配置值较低,前者低1/2,后者低一倍。
stack size是每个用户进程可使用的堆栈大小(我们知道其实每个命令实际上发送到数据库服务端后,都是有一个单独的线程配合工作的,不知道这个知识的,现在你们知道了),那么如果我本身啥都没干,仅存储需要执行的命令字节就已经不够了,那这个命令是否能执行成功,结果很难说,要看当时实现这个功能的研发到底有没有考虑到有一天会有那么一个人写那么老长的命令,还不要脸的发给服务器端了
而stack guard size我理解是sybase数据库的一种保护机制,为了应对服务器端进程工作时堆栈空间不够的情况,专门划出来的一个可溢出的大小,单个连接最大可使用堆栈大小为stack size
+stack guard size
之和。但是!!!看下面这个图片,感觉我的理解有误呀,好像这个守护栈大小是为了栈溢出时自动调度,尝试重新执行的概念呀?希望英文好的同学可以帮忙翻译一下,到底什么意思。
既然知道了这俩参数控制着单个连接的可用堆栈大小,且我们确定了好用的地区这俩配置的值比不好用的大,又有前面试验出来的sybase单个命令最大字节数限制超限引发报错的结论做支撑,那就直接修改吧。改多大呢?先改成和不出错的地区一样大,然后…特么的sybase修改配置竟然需要重启!!!但这可是NP呀,哪儿能随便重启,安排驻地下班后重启,过程中有点儿小插曲,不过好在最终下班后重启成功了,再试验一下,问题解决了!!!真的是不容易呀!!!
参考资料
stack size官方说明:http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc31654.1570/html/sag1/X30093.htm stack guard size官方说明:http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc31654.1570/html/sag1/X43216.htm
PS:sybase资料是真的少,而且真的不好调整呀,还不支持原生分页,啥时候才能彻底干掉他呀???