建荣写过一篇《维护之夜,说点故事和经验》,讲了一些维护工作中碰到的事情,虽然我的本职工作不是DBA,但是已经从事了十多年的应用运维工作,应用同样需要各种维护,包括上线投产、应急处置、迁移、演练等,只是维护的对象不仅仅是数据库,而是应用为核心展开的,在这个过程中,碰到了很多让我印象深刻的事情。
其实很多事情,都是靠经验积累,我算是”踩“在前辈的肩膀一路扛过来的,老司机带你吃鸡,可能就是这意思。
找些很有意义的维护工作和经验,记录于此,算是给自己提个醒了。
最粗心的一次
当时维护一个后台指令,某项工作就是负责XX数据的维护,简单来讲,就是客户提需求,我们负责增删改这些数据,展示给前台。当天收到个需求,更新某条数据的几个字段,于是和往常一样,开始编辑SQL,其实就是条UPDATE,但是鬼使神差,没写WHERE条件,结果可想而知,这张表的所有数据都被更新成一样的了,而且还是工作日的下午,客服立刻就打来了电话,问是怎么回事儿?这种感觉,可能很多人都曾经碰到过,脑皮一紧,嗡嗡作响,
庆幸的是,这就是个查询的功能,而且测试数据库,就是生产的镜像,于是发挥了文本粘贴复制剪辑的技术,拼出插入语句,快速执行,恢复了生产。
案例提醒了我,
1. 时刻记住“生产无小事”,生产上的任何操作都需要谨慎,要有敬畏之心。
2. 任何有计划的生产操作,避免临时现写操作流程,对重要的操作,需要提前在预投产等环境演练,验证操作流程,如有条件,生产应该双岗,无论对老手,还是新手,降低犯错可能。
3. 具备快速备份恢复的策略。
4. 培养良好的心理素质,犯错就担着,不犯相同的错。
最坑人的一次
配合某客户,迁移他们自己的数据库,需要我们的应用,改下数据库IP、账号和密码,原则上只需要改下配置文件,重启应用生效。按说应该是一次非常简单的操作,但是02:00A.M.开始,做到了04:00A.M.,发现应用重启了,就是不能连上数据库,甚至将用户名和密码都改成了和原来相同的,都提示监听错误,数据库端都是正常的,而且另外一套应用已经改好生效,连接正常。我被薅起来,再次验证了数据库正常、应用正常,一直搞到快早上,业务高峰,就快到了,都紧张起来了。因为这是套老旧系统,在我入职前就已经上线了,代码的管理就是放在服务器个人路径下,没做任何版本管理或是代码库,于是怀疑是不是生产的代码不是我们所想象的?在个人路径下,搜索所有该程序的版本,发现有个版本的连接数据库的部分使用的硬编码,用户名、密码、连接串都和旧库都是相同的,虽然这个文件的更新日期不是最新的,但是从现象上,和生产是一致的,改了连接串,重启应用,不能连接,如果应用硬编码的连接信息,自然不可能连上。
没时间考虑了,只能硬试了。原则上配合工作,只提了配置文件变更的流程,不能改动程序,但是这个时候,破戒就破了,改了程序中连接数据库的部分,注释硬编码,编译、上传、重启、请求调用、处理正常,一气呵成,之所以说惊险,因为和客户约定了搞成的时间点,07:20A.M.前搞定,否则就回滚,而且会造成东南亚两个XX延误,好在提前几分钟,恢复了正常业务。
案例提醒了我,
1. 线上的代码版本管理的重要性,如果线上用的是什么版本都不知道,进坑不是今天,就是明天。
2. 生产上的任何操作即使是认为很简单的配合,都需要更谨慎地对待,上线、回滚、应急流程,需要准备充分,演练正确,需要的时候,才可以从容应对,十次用到一次,你就是赚的。
最踏实的一次
某个业务涉及很多的客户,逻辑几乎相同,但是用的不同的表和应用,由于应用设计之初无论是索引,还是数据清理,都是没考虑过多,导致运行一段后,开始执行缓慢,需要进行优化。其实方案不难,一个是创建索引,另外一个就是数据清理策略,N天前的数据,每日定时从交易表导入历史表,降低交易表的数据量。
难点就在于牵扯的用户较多,考虑某些因素,必须一次迁移,停机时间很短,需要严格定义好每一步操作的流程和耗时,以及客户的联调配合,准备上很充分,打印出来表格,人手一份,分工实施,严格关注时间点,最大限度地缩短停机时间,整个操作下来,比较顺畅,无论是我们的,还是客户配合,比预计提前完成了所有的工作。
案例提醒了我,
线上工作的准备,多细可能都不为过的,正所谓”台上一分钟,台下十年功“,没这么夸张,但是也能说明,准备的充分了,实际操作时,才会更顺畅,才会游刃有余。
最可气的一次
其实和上个案例是同一天,我们完成了这个工作,部门另外一个团队在上线时,碰到了个问题,帮助支持一下。他是一个Tuxedo应用,正常上线,请求出现了不能调用的现象,应用日志没提示任何的错误,但就是请求不通,无论是在应用中增加trace,还是测试各种场景的请求,都是没作用。叫起了很多大牛来支持,都是没给出具体的解决方案。
最可气的,是靠着重启Tuxedo Gateway,解决了这个问题。很可能是因为某些原因,上线过程中,导致了Gateway和应用之间的连接中断,但是这个信息,没在任何日志中进行暴露,无从知晓。
案例提醒了我,
看来重启大法,在很多场景,都算是最有效的。有事儿没事儿,重启一下,往往就可以解决你的问题。
最崩溃的一次
为了配合机房搬迁的工作,需要将操作系统和中间件的版本进行升级,涉及了将近150个C程序改造和编译,从分配任务、组织人员改造、测试、联调、制定投产计划,涉及了几个月,最重要的一步,就是迁移当晚的工作安排,因为一些不可抗拒的原因,150个程序需要一次性迁移完成,涉及到了全国几十个客户,我们按照客户、涉及业务、涉及数量,进行了多维度分组和具体的配合操作,准备工作算是比较充分了。
迁移当晚00:00a.m.,一声令下,集体操作,各司其职,有条不紊。好戏才刚开始,大部分的应用,都正常升级、验证完成了,有些小问题,基本都克服了。但是某个应用,功能是读取客户的数据库同步数据到本地,总是出现执行一会就重启的现象,倒吸一口冷气。
经过多次测试,发现个规律,当客户数据库中的数据超过500条的时候,就会出现自动重启的现象。这就很诡异了,看了一下历史,一般正常同步,不会出现超过500条数据的情况,之所以今天出现,还是因为停机时,数据被积累在客户的数据库,当启动同步程序,此时数据就已经超过了500条,达到了几千条,但是程序中为何是这个逻辑,显然在快到凌晨的时间,脑壳已经不转了,只能先让客户将数据删除到500条以下,保证业务正常。
稍微补了个觉,鉴于安全生产,需要解决这问题。再次浏览程序,发现有个读取数据的逻辑,使用的是游标,一种是500条以下的操作逻辑,一种是超过500条的操作逻辑,在后者的逻辑中,批量一次读数据,有个判断,SQLNOMORE,即1403的判断,表示本次循环没数据可读了,但是接下来和其他一些错误码混在一起执行了重启指令,因此每次执行,到这都会重启。正常的时候,数据量小于500条,逻辑正确,因此没出现问题。至于为什么超过500条出错逻辑没做过验证,这个就无从考究。当晚应急上线,增加了逻辑判断,才算彻底解决。
案例提醒了我,
程序的任何逻辑都应该充分测试,往往出现问题的,都是极端逻辑。
最紧张的一次
某个实时性要求很高的系统,某日00:30A.M.-01:00A.M.出现响应慢,导致正常业务受到了影响,通过应用日志,定位到是一条UPDATE语句执行慢,执行计划很简单,用的还是INDEX UNIQUE SCAN,但是逻辑读很高,通过排查,这个时间段,删除涉及这张表的历史过期数据的夜维在执行,应急操作是kill了这个程序,业务就恢复正常。临时解决了问题,但是夜维挂起了,在问题解决期间只能人为定期删除数据,避免交易表数据量的增长,保障正常业务的执行效率。
这个业务牵扯到了一些SH上的影响,不久前刚投产,而且这个故障,发生在了一个非常敏感的时期,即将到XX重保的关键期,各方都很紧张,不能给XX添堵。记得当时从00:30A.M.和同事们远程处理应急、分析问题到了05:00A.M.,然后不到09:00A.M.又到公司和领导们一起分析问题跟因、写故障简报,折腾了一天,当然没根本解决,在随后的一两周做了几次应用的紧急上线,在线上模拟了两次终于复现了问题,才确定解决方案是可靠的。
排查的过程,还是充满了曲折,可以参考,
《《一次Oracle bug的故障排查过程思考》的问题重现解决》
问题的根源,是碰到了ASSM中一个叫space search cache的控制,可以通过patch或是10019事件解决,当时的数据库版本没有对应的patch,因此是采用关闭这个事件解决的,但是这个坑,追溯应用的源头,是在做delete删除数据的时候并未采用批量的方式,而是一次性删除几十万数据才提交一次的形式,这会让对相同表操作update语句消耗超高的逻辑读,进而影响业务。
从应用端看,优化的操作就是避免一次性删除,改为批量删除。
案例提醒了我,
其实有时候生产上出现的问题,如果在应用设计开发的时候,多考虑些,往往就可以避免,例如这个案例中,数据的删除操作,应该采用批量,而不是一个大事务处理,像这种问题,应该遵从设计开发规范,这才是王道。
都说运维工作不好做,一方面是因为往往是出于救火的状态,而且都是非常紧急的场景,更多是在夜间,对身体上和心理上都是一种“摧残”,另一方面,应急解决问题,可能能做到,但是找到问题的根因,并提出解决方案,就需要各种知识的综合、测试场景的尝试、合理的“猜测”论证等等,对人才的要求,其实还是很高的,更需要的是实践的积累,“罗马不是一日建成的”,但是从另外一个层面讲,单靠运维人员,系统不出问题,绝对不可能,需要开设计开发阶段,就带着优化的一些理念来做,我们曾倡导面向运维的开发方式,无论是架构设计、应用日志、异常处理、高效代码,都为了让系统稳定持续高效运行的目标,而不是仅仅功能上可用。同时,制定相关的规范,遵照执行,往往其中就涉及到一些运行时会出现的坑,同一个坑,不进两次,应该是基础要求。
除了以上的案例,其他一些维护操作时需要注意的,
1. 例如一些远程连接的终端,可以将连接生产环境的窗口字体设成红色,以提高警示作用。
2. 生产上的任何交易操作,点击回车前,都可以停下,确认无误再按,不怕慢,就怕错。
3. 双岗不是摆设,要起到他的作用。
4. 充分进行生产操作的制定,不要想当然,理解墨菲定律。
5. 锻炼好身体、心理,往往很关键。
向运维人员致敬!