
前不久,熊二作为StrongBear的核心员工,也遇到了一件尴尬事。事情是这样的:
一天,负责部署及监控的运维人员小刚向光头强强总报告一个现象,就是在部署最新的一个应用的时候,服务器应用迟迟不见成功,一直在“starting….", 最后,很遗憾的超时,变成部署失败。
光头强意识到问题很严重,无论如何也得让这个部署能正常才行啊。新版本毕竟比上一个版本多了很多补丁,还包括一些新功能。
问题卡在哪儿了呢?
光头强让熊二去查探一下。熊二先看看了服务器应用的启动日志,发现它一直在执行和初始化数据库的liquibase脚本 (liquibase脚本是最流行的在线变更工具库之一),似乎最后没有执行完,直至超时。
熊二回想起,自上一个版本直至这个版本以来,liquibase脚本中变动的地方只有两个,一个是对某表的字段col_a, 长度从原来的64扩大到128,并且允许为空;另一个就是对某张表cc_ownerids的access_time字段创建一个索引。并且采用的还是:
CREATE INDEX CONCURRENTLY idx_ccownerids_accesstime on cc_ownerids(access_time);
不是说concurrently不会block对表的正常访问,进而不会影响业务吗?
范围缩小了很多。第一个表的字段长度变更,在PostgreSQL里头基本上是秒变,很快就会完成。那么疑点就出在这个建索引上边了。
于是,熊二再上pg_stat_activity一查,果不其然,就卡在这条语句上,发现那个create index 居然好几分钟都没有执行完。
熊二再顺便查了一下那张目标表:cc_ownerids,总共有记录1800万条,不算特别大,但也很大了。
事情到了这一步,咋办?
有两种方案:
1)将liquibase脚本中的建索引那一段直接去掉,重新编译并打包,部署上去,这个在时间上很快;然后在部署的同时,DBA相关人中人工对目标库进行索引的创建,可以通过调度客户端工具进行所有数据中心(Region)的变更。(正应了:create index concurrently不影响表的正常访问)
2)liquibase脚本不动,因为它里边的逻辑是:如果没那个索引,就进行创建;让部署人员推迟部署,先让DBA对所有的Region的这个表进行索引的创建,全部建完以后,重新进行部署。新的数据中心,直接部署就行,因为表里头没有数据,速度很快。
上边两个方法都可以。1)相当于一定程度的并发,但是对于新部署的服务应用,那个索引还是没有。需要事后重新把那段逻辑给加上。
经过比较,光头强还是决定采取 2)这个方案。最后各个Region的服务全部得到更新。
也基于此,熊二也得到了一些教训:
1)应用层并不能取代所有DBA的维护工作,一些耗时的初始化操作,肯定是不能放到liquibase里头,搞不好会酿成事故;
2)纸面上的结论,听着看着是正确的,但需要小心求证,有的东西有两面性;比如这个create index concurrently, 好处确实是不影响业务,但这里就没有预计到它很耗时,不能串行的放到初始化的相关代码里头。
经此一事,熊二对待数据库相关问题的处理,更显得谦恭谨慎了。
我是【Sean】, 欢迎大家长按关注并加星公众号:数据库杂记。为你提供及时更新。

原文作者:数据库杂记;如有侵权,请联系管理员删除。