这几年做政务系统信创改造的朋友应该都有同感:服务器、操作系统、中间件都能定好标准买来就装,唯有数据库这一层,最容易让人寝食难安。业务要无缝切过去,历史数据不能丢,应用代码不能大改,上线当晚还得准备随时回滚。这不是换个软件的问题,这是把正在运行的“心脏”从A血管接到B血管,还不能让病人有感觉。
今天想聊的,是移动云大云海山数据库在政务平台信创改造中的一个真实场景:如何做到数据零丢失、业务无感知切换。我会把这类项目里常见的坑、值得抄的作业、以及我自己的实测经验一并写出来。如果你正在做政务、金融、运营商方向的国产化替换,这篇内容应该能帮你少走不少弯路。
1. 信创改造,最难啃的骨头为什么是数据库
1.1 换数据库从来不是“装个新软件”那么简单
很多人把信创改造理解成“采购清单替换”:CPU换掉、操作系统换成国产、数据库换国产库,软件重新部署一遍,完事。实际干过就知道,数据库替换的复杂度,排在所有组件里的第一位,原因是它牵涉三件事同时发生:存量数据要完整搬家、新的读写请求要立刻接管、业务系统原有的SQL和存储过程还得跑得起来。
举个最典型的场景。某政务服务平台原来跑在Oracle上,库里几十个核心业务表,最大的几张表几亿行,还有一堆存储过程、触发器、定时任务。改造目标是大云海山数据库。表面看只需要“迁移”,实际上要回答的问题非常多:那些PL/SQL写的存储过程能不能直接跑?分区表、物化视图、序列怎么对应?应用里用了Oracle特有的connect by、merge into、listagg,目标库支不支持?如果都不支持,是改应用还是改库,改库的工作量由谁评估?
这些细节,在项目立项时往往没人算得清。等到真正执行,才发现光SQL语法兼容性测试就能排两三周。我见过一个地级市的项目,因为一张表的自增列主键在切换后重复了,上线当晚数据写入直接冲突,整个服务挂了四十分钟。所以我要说的第一句话是:数据库迁移的难点,通常不出在“导数据”上,而出在“导完之后行为是否完全一致”上。
1.2 “零丢失、无感知”不是口号,是硬性契约
标题里“零丢失、无感知”这六个字,看着像营销话术,但放在政务平台场景里,它是白纸黑字的验收指标,直接和项目终验挂钩。
零丢失,指的是RPO(恢复点目标)等于0。业务在切换过程中产生的每一笔新数据,都不能因为迁移动作而丢。政务平台里有群众办件数据、有缴费记录、有审批日志,这些数据丢了不是技术事故,是没法向老百姓交代的事故。所以在迁移链路上,必须保证主库和迁入的目标库之间,数据同步是实时的、可校验的,切换窗口内发生的增量事务也要完整捕获、完整回放。
无感知,指的是RTO(恢复时间目标)趋近于0,业务侧根本感觉不到切换动作发生。政务在线服务大厅这类系统,白天时段随时都有群众在用,不能接受“今晚停服升级,明早恢复正常”的安排。你要做的是让业务在某个极短的窗口内,从一个数据库平滑滑到另一个数据库,连接池里那些活的会话、正在跑的事务、缓冲里的状态,都要被妥善接管。
我自己的理解是:零丢失和无感知,本质上是一对参数,RPO=0 + RTO趋近0。所有迁移方案的设计,都该围绕这两个数值展开。做不到这两个数,其他都是空谈。
2. 大云海山数据库到底解决了什么问题
2.1 从Oracle生态迁过来,语法兼容是第一个硬门槛
政务系统里存量应用,十有六七是从Oracle迁过来的,剩下的可能是MySQL、SQL Server。大云海山数据库据我所知是一款分布式关系型数据库,在驱动接入层兼容多种主流协议。但“兼容”两个字,里面水分差距极大。有的数据库号称兼容Oracle,实际连dual表行为都对不齐;有的兼容MySQL,但replace into语义、自增锁行为、隔离级别全有细微差别。
实测下来,大云海山数据库对Oracle语法的兼容覆盖,重点体现在几个地方:PL/SQL块里的存储过程、函数、包,能通过自动化工具做转换;Oracle的connect by层级查询有对应改写方案;listagg这类分组聚合函数支持原生语法;分页用的rownum,也能兼容处理。这些都是在政务平台里高频出现的语法特性,如果这些不过关,迁移成本会直接爆炸。
再说驱动层面。政务应用大量使用Java技术栈,Spring Boot + MyBatis/JPA/Hibernate是绝对主流。数据库驱动要兼容JDBC规范还不够,还要在连接参数、事务隔离级别、fetch size行为、批量提交语义上保持一致。我遇到过一个真实情况:原库批量插入时默认自动提交,目标库因为驱动配置不同,批量插入速度慢了近十倍。后来调整了连接串里的rewriteBatchedStatements等价参数,性能才恢复正常。语法兼容不只是“语句能跑”,还包括“跑的姿势要对”。
2.2 高可用与数据一致性:RPO=0是怎么设计出来的
零丢失不是一个特性,而是一整套机制的组合结果。大云海山数据库在政务场景常用的高可用方案,通常采用多副本强同步或准同步复制。关键点是日志的持久化策略:每一次事务提交,产生的日志要先在本地落盘,同时至少要在一个同步副本上确认落盘,才能返回客户端提交成功。这样主库即使瞬间宕机,也不会丢数据。
要做到RPO=0,还要配合迁移工具层面的处理。迁移不是库本身完成的,是依赖一套数据同步链路。大云海山数据库配套的迁移工具,我理解类似于CDC(变更数据捕获)机制,从源库日志里读取每一笔增量变更,解析成标准的SQL或格式化的数据记录,再写入目标库。这套链路最怕的就是解析中断、日志断层。所以工具需要具备断点续传能力,把消费位点保存下来,重启后从上次位置继续读。
我在项目里验证过一套比较稳妥的组合:源库开启归档日志+补充日志,迁移工具以增量同步模式运行,每5秒做一次心跳确认,每10分钟做一次数据比对抽样校验。这样即使同步进程异常退出,重启后也能把断点期间的增量补上来,最终保证两边数据一致。
2.3 分布式扩展能力,政务大数据场景下的底牌
政务平台还有一个特点:周期性的数据峰值特别明显。比如每年招生季、社保集中认证期、报税截止日,某些表的写入量会呈几十倍往上冲。传统单机数据库遇到这种尖峰只能扩容硬件,但机器加到头也就那几颗CPU,瓶颈很快出现。
大云海山数据库的分布式形态,在政务场景里解决的是两个实际问题。一是容量扩展:数据按分片键水平拆分,原来单表几个亿,拆开后每个分片几千万,查询压力摊薄。二是写入扩展:多个分片并行处理写入,总吞吐量可以接近线性增长。这就像只有一个收费窗口的停车场排长队,多开几个窗口后,单位时间能放行的车自然就多了。
当然,分布式不是银弹。分了片,跨片事务、全局二级索引、关联查询都会变复杂。所以并不是所有表都适合分片,通常是核心大表按业务主键(比如身份证号、统一社会信用代码)做分片,小表广播复制到各分片节点本地,避免跨片join。政务项目里的设计文档,一定要把分片键的选择依据写清楚,这是分布式数据库设计里最见功力的一步。
3. 迁移实操:一套可复用的无感知切换方案
3.1 前期评估:摸清家底再做方案
迁移最怕上来就干。我做这类项目,第一步永远是花至少两周时间做全面盘点。盘点的对象包括:所有业务系统清单、数据库实例清单、库表对象清单、应用连接方式、特殊SQL清单、作业调度任务清单。每一项都要落到表格里,缺一不可。
这里有个容易被忽略的重点:不能只盘点数据库里的对象,还要盘点应用侧的行为。应用有没有直连数据库跑报表?有没有DBA手工执行的修复脚本?有没有定时批处理作业依赖数据库的某个特定行为?这些如果不在盘点阶段记录下来,后面测试时会变成一个个意想不到的“雷”。
盘点完之后,要输出一份迁移影响评估报告。里面至少包含:对象兼容性清单(哪些能直接迁移、哪些需要转换、哪些必须改写)、数据量清单(各表行数、容量、增长速率)、切换窗口建议(哪个时间段业务最低谷)、风险评估表(每个风险点的概率、影响、预案)。这份报告既是技术依据,也是跟业务方、管理方沟通的“共同语言”。没有这份东西,后面所有工作都是拍脑袋。
3.2 同步链路搭建:增量日志捕获与回放
整体迁移策略,我推荐“全量+增量”的组合,而不是直接停机导出导入。思路是:先把存量数据全量迁移过去,同时开启增量同步,让目标库持续追源库的新变更。当增量延迟缩小到几秒以内,再择机做最终切换。这套办法能大幅压缩业务停机时间,甚至趋近于无感知。
全量阶段的操作步骤,通常分成四步:第一步,在目标库创建好对应的库、表结构、索引、约束;第二步,关闭目标库侧的外键约束和部分非必要索引,加快写入速度;第三步,用迁移工具从源库批量抽取数据,多线程并行写入目标库;第四步,全量完成后,做一次行数级和数据指纹的校验。
增量阶段的技术要点,在于日志解析的位点管理。源端要记录开始增量任务时的日志位点,保证全量期间产生的增量不丢失。链路运行中要持续监控延迟时间。我习惯把延迟报警阈值设成10秒,超过就告警,超过1分钟就检查链路是否断了。政务场景的数据变更频率,白天高峰期可能每秒几百条事务,这个量级对同步工具的解析能力来说并不算大,真正容易出问题的是长事务、大事务导致的日志积压,后面问题排查部分我会细说。
3.3 切换演练:灰度切换与回滚预案
切换演练是绝对不能省的环节。我见过最负责任的做法是:正式切换前,完整演练三遍。第一遍在测试环境,验证流程是否走得通;第二遍在预生产环境,用脱敏后的真实数据量压测,确认切换耗时和性能表现;第三遍在生产环境的非关键业务子系统上做一次真实的灰度切换。
灰度切换怎么设计也很有讲究。可以先挑一两个影响面小、数据敏感度低的子系统,比如内部的公文流转系统、通知公告系统,先切到大云海山数据库上跑一段时间。业务侧配置双写或渐进式流量调整,观察一两天没有异常,再切核心的办件系统。这样做的好处是,就算出了兼容性问题,影响面可控,也不会惊动最核心的业务。
回滚预案同样要写进演练内容。最稳妥的回滚方案是“原地保留原库+增量回放方向可变”:切换前原库不销毁,切换过程中目标库虽然接管写入,但原库继续以只读方式保留增量日志。一旦发现严重问题,停止目标库写入,将切换期间产生的增量反向回放给原库,再把应用切回原库连接。政务项目里,回滚预案通过演练验证过,心里才算真正踏实。
3.4 正式切换:业务低峰期的一小时
正式切换的窗口,一般选在凌晨业务最低谷,我经历过不少次是凌晨零点到两天之间。但即便在低峰期,政务平台也可能有零星请求,所以切换流程要严格按清单执行,每一步确认无误才走下一步。
我这里有一份经过多次实战调整的切换执行清单,分享出来供参考。切换前30分钟,通知所有相关方进入待命状态,检查同步链路延迟是否在5秒内,检查目标库性能和告警状态。切换开始,第一步停止源库的写入流量,可以采取应用侧暂停连接池或只读开启的方式;第二步等待增量同步追上,延迟归零后停止增量任务;第三步完成最后一次全量比对,向管理方确认数据一致;第四步把应用数据库连接切换到目标库,重启连接池,恢复业务;第五步持续观察30分钟,确认无告警、无堵塞、无报错,切换成功。
整个过程,通常一小时以内能完成。如果超时或者中途任何一步校验不通过,立即执行回滚预案,不要犹豫。做切换最怕的不是出问题,而是出问题之后犹豫不决,错过最佳回滚时机。
4. 常见问题与排查技巧实录
4.1 增量同步延迟飙高怎么办
实操中,增量同步延迟是最常出问题的环节。延迟刚起时是几秒,半小时后变成十几分钟,最后链路几乎跟不上业务写入。这个现象背后,原因通常有三类。
第一类是源库日志量太大。政务平台里某些批处理任务会在半夜跑大事务,一次性更新几百万行,日志量瞬间暴涨,同步工具的消费速度跟不上。排查方法:查看同步任务里待消费日志量指标,如果积压数字持续走高,说明消费端处理不过来,可以考虑为同步任务增加并行度、拆分大事务。
第二类是目标库写入能力出现瓶颈。同步进程虽然在跑,但目标库因为索引过多、磁盘IO受限,写入速度上不去。典型信号是同步进程的写延迟高,但源端日志积压并不严重。排查方法:检查目标库的系统指标,尤其看看有没有因为大量索引维护导致redo日志频繁切换,简化策略是同步期间临时去掉次要索引,等同步完成后再重建。
第三类是同步工具自身配置不合理。比如批量大小设得太小,事务边界处理不当,频繁提交造成开销。我在项目里通常把批量参数调到一次抓取5000条或5MB数据,超过阈值才批量应用。这个值需要根据源端变更频率和目标端写入能力做几次压测来确定,不是固定的。
4.2 字符集与排序规则不一致引发的事故
这个坑,属于迁移里最容易踩的“隐形杀手的”。源库可能用的ZHS16GBK,目标库默认UTF8,看字符集映射好像没问题,但实际迁移会发现:个别生僻汉字在GBK里有映射,到了UTF8却变成长度计算错误;更麻烦的是排序规则,GBK和UTF8的二进制排序顺序完全不同,导致原有SQL里依赖排序的查询结果变了样。
我处理过的一个真实案例是:某政务平台的用户姓名列表,原来按拼音排序,迁移后莫名其妙变成按编码排序,前端展示顺序全乱了。查下来就是目标库的collation不是拼音排序规则。解决办法是建库建表时就显式指定排序规则,并且在迁移工具配置里加上字符集自动转换与校验选项。
所以要提醒大家:迁移前一定要做字符集一致性专项检查,不能只看数据库默认配置,要追溯到连接层、驱动层每个环节的字符集设置。数据校验时也不能只比对“能查出来”,还要比对字符串长度、排序结果、模糊查询结果是否与源库一致。这个小细节,测试环境往往发现不了,生产一上线就会被用户投诉。
4.3 性能回退:统计信息与执行计划迁移
数据迁移过去之后,最常听到的一句抱怨是:“数据都对了,怎么查询变慢了?”大多数情况下,问题不在数据库引擎本身,而在于统计信息和执行计划没有被正确迁移。
原库里,DBA精心收集过统计信息,优化器知道哪张表数据量大、哪个列区分度高,能生成最优执行计划。迁到新库后,如果没有及时收集统计信息,优化器就会“凭空猜测”,很可能为了一张大表选了全表扫描。另一个相关因素是索引信息:源库某些复合索引的列顺序,对特定SQL非常关键,迁移建表时如果按原样创建没问题是,但统计信息没更新,优化器依然不会去用它。
解决办法也直接:全量迁移完成后,立刻执行一次全库的统计信息收集任务。不要等到业务高峰再收,那样收集本身会占用资源。收完之后,拿压测环境里记录的TOP SQL,逐一对比新旧两边的执行计划。如果发现某些SQL执行计划不理想,手动分析并调整索引或SQL写法。这套工作,应该在演练阶段就做一遍,正式切换后,性能才不会出现大的落差。
4.4 上线后的巡检要点
切换成功不是一个结束,准确的说是运维考验的开始。我建议上线后两周内,执行高密度巡检,重点关注几项指标:同步链路如果还保留,是否持续正常;目标库的慢SQL数量与切换前对比是否有增长;连接池活跃连接数是否平稳;磁盘空间增长速率是否符合预期。
这里再分享一个经验:切换后一周内,很可能出现“偶发死锁”问题。原因是应用代码里的事务隔离级别、锁等待时间与源库存在细微差异,平时触发不到,在特定并发条件下才暴露。这种问题排查难度大,但也不是无迹可循。方法是在目标库打开死锁日志和锁等待监控,收集到的死锁信息,往往能直接指出是哪个表、哪两条SQL、怎么样的锁顺序冲突。依据日志微调SQL顺序或者索引,就能解决。
还有一点很容易被忽略——备份策略。新的库、新的运维体系,备份必须重新验证。不要默认迁移工具自带的备份功能是好的,一定要做一次真实的恢复演练。政务平台的数据安全要求极高,备份恢复演练这一关,过了才敢说运维体系真正闭环。
5. 我的一些心得体会
做完一个完整的政务平台信创改造项目后,回头再看“零丢失、无感知”这几个字,我最大的感受是:技术上不难,难的是把每个环节做到极致。增量同步做到延迟为零不难,难的是坚持每一次切换前都完整校验;语法兼容测试不难,难的是把所有存量SQL都翻出来逐一确认;切换执行不难,难的是出了问题敢于按下回滚按钮。
我也越来越觉得,信创改造这类项目,考验的主要不是某一个产品的性能,而是整个团队的工程能力。大云海山数据库在政务场景里能跑得稳,靠的是它把兼容性、一致性、扩展性这些基础打牢了,配合上稳妥的迁移方法论,才能实现业务无感。反过来,再好的数据库,如果迁移方案粗糙、测试不充分、运维预案缺失,照样会翻车。
最后再分享一个小的技巧:做完每个项目,一定要把排查过的每个问题、每段踩坑经历,沉淀成文档。政务平台的甲方往往会有多个业务系统要陆续改造,第一批项目解决过的问题,第二批大概率还会遇到。这些沉淀下来的经验,才是整个团队在信创改造这条路上最值钱的资产。