
很多人把数据库迁移类比成搬家——把东西打包、运过去、再 unpack。但真正做过生产环境 SQL Server 迁移的人都知道,这个比喻害死人。搬家可以接受短暂的秩序混乱,可以忍受几天找不到东西。数据库迁移不一样,生产库一旦出问题,业务就是停摆,损失按分钟计。
我参与过大大小小十几次 SQL Server 迁移,从 2008 升级到 2016、跨版本的数据迁移、主从架构调整、甚至是实例层面的 OS 级别迁移。每一次都踩过不同的坑,也因此对「迁移到底要注意什么」有了比文档更实在的理解。这篇文章,就是把这些经验摊开来,不求面面俱到,但求说到点上。
很多人迁移是因为「版本太旧了」或者「领导说要升」。这个理由不充分。迁移是一项高风险操作,如果没有明确的目标,就像没有靶心就开枪,打得再准也没意义。
常见的迁移动机应该是可量化的:比如当前版本在 xxxx 年终止支持、现有硬件无法支撑业务峰值、某个新版本特性是业务急需的(比如 Always Encrypted、查询存储等)、或者审计要求必须满足特定合规级别。只有目标清晰,迁移方案的设计才有取舍的依据。
这一点怎么强调都不为过。我的建议是:在动手之前,先跑 Microsoft Data Migration Assistant (DMA。这个工具会扫描你的源数据库,识别出迁移到目标版本时会遇到的兼容性问题,包括:
但我必须提醒的是:DMA 的报告要仔细看,但不要盲目全信。它会报出一些「警告」,有些实际上是 benign 的。比如某些查询在兼容级别降低时会触发警告,但你的业务逻辑根本不会触发那些路径。我见过有人被 DMA 报告吓得不敢动,最后花了两周去「修复」一堆根本不是问题的警告。拿到报告后,先按严重程度分类,和开发团队一起 review 每个警告的业务影响,再决定要不要处理。
我第一次做大表迁移时,低估了数据量的影响。当时觉得 200GB 数据量不大,结果由于没有考虑表的具体分布——一张分区表占了 180GB,索引碎片率超过 85%——实际迁移时间超出了预估的三倍,差点影响业务恢复窗口。
正确的做法是:
SQL Server 迁移最常见的两条路:备份还原和复制迁移(通过 Log Shipping、Always On、或者第三方工具)。各有各的适用场景。
备份还原的优势是简单可靠,适合数据量不太大(100GB 以内)、可以接受较长停机窗口的场景。但它有几个坑:
复制迁移(Log Shipping / Always On)是生产环境推荐的方式,优势是停机窗口可以做到极短(几分钟级别),且可以在真正切换前做多次演练和验证。但它对网络带宽有要求——如果源库和目标库之间的网络延迟高或者带宽低,同步延迟会成为噩梦。实践中我发现,有些团队低估了生产环境的网络复杂度,特别是在混合云或者跨机房的场景下。
异机迁移(也就是在新的服务器实例上重新搭建)是目前的主流推荐,原因是:
原地升级(In-place upgrade)看起来最省事,但我在吃过亏之后基本不推荐。原因很简单:一旦升级失败,你没有可以快速回退的环境,升级过程本身不可逆。如果非要做原地升级,强烈建议先在虚拟机上完整模拟一次升级过程,包括所有补丁、配置变更,然后再在生产环境操作。
很多团队迁移后直接让数据库以默认兼容级别运行,这没问题——但要清楚知道你在用的是多少。SQL Server 2016 开始默认兼容级别是 130(对应 SQL Server 2016),而如果你的应用设计上针对的是 110(SQL Server 2012)的行为,混用可能会导致查询结果不一致。比如:
建议迁移后先用兼容级别保持原状跑一段时间,让应用充分验证,确认无误后再逐步提升兼容级别,而不是一次性拉满。
如果源环境里有大量的 Linked Server 配置,这些信息不会随着数据库迁移自动生效。你需要:
还有一点容易被忽略:数据库所有者(owner)变更后,某些 stored procedure 的权限可能出问题。比如某个 SP 用 EXECUTE AS 写了特定用户,迁移后这个用户可能不存在了,导致 SP 编译失败或运行时权限错误。建议迁移后执行一次 EXEC sp\_change\_users\_login 'Report' 来检查孤立用户。
SQL Server 的查询优化器在不同版本间会有变化,同样一条 SQL,在旧版本用得好好的执行计划,迁移后可能变成全表扫描。这不是 Bug,是正常行为,但如果没有主动检测,线上会突然变慢。
我的做法是:迁移前,用 第三方工具抓取一批高频查询作为基准。迁移后,拿同一批查询的实际执行计划做对比。如果某条 SQL 迁移后的执行计划明显变差,先不要急着加 hint,先分析背后的原因——是因为统计信息过期?是因为索引丢失?还是基数估算器模型变化?找到根因再动手。
这里有一个很多人不知道的点:SQL Server 的统计信息(statistics)是绑定在数据库级别的,理论上迁移数据库时统计信息会一起过来。但长时间运行的库,统计信息的采样可能已经高度偏斜,迁移后优化器拿到的可能还是「旧照片」。建议迁移完成后,在关键大表上手动 UPDATE STATISTICS 一次(带 FULLSCAN 选项,如果窗口允许的话)。
这个问题在迁移后特别容易爆发。很多存储过程依赖参数嗅探来生成高效执行计划,但一旦数据分布发生变化(比如表在迁移前做了一次大批量导入),同样的参数可能产生完全不同的计划。经典表现就是:迁移后某些 Stored Procedure 在某些参数值下性能极差,而其他值下正常。如果你的业务有这种特征,迁移后要做**压力测试**,而不是只跑功能验证。
即便前面的准备工作都做得很充分,切换窗口那段时间依然需要极度专注。我的经验是:
切换完成后,业务团队的验证不能只停留在「页面能打开」。至少要验证:
这部分值得单独说一说,因为国内现在有大量 SQL Server 迁移项目,实际方向不是跨版本升级,而是异构迁移到国产数据库,金仓数据库(KingbaseES)是其中比较常见的选择之一。
政策层面,信创要求(信息技术应用创新)是一个重要推动力。很多政府单位、金融机构、大型企业被要求在限定时间内完成核心系统的国产化替代。技术层面,金仓等国产数据库这些年成熟度提升明显,兼容 Oracle 和 SQL Server 的能力也在增强,不再是从零起步。
但现实情况是:这种迁移的难度远高于同类型数据库的版本迁移。SQL Server 到 SQL Server 迁移,底层存储引擎是一致的,兼容性好很多。而 SQL Server 到国产数据库,在 SQL 语法细节、数据类型精度、存储过程语法、事务隔离级别实现等方面都有差异。
语法适配是最耗时的工作。 SQL Server 的 T-SQL 扩展非常丰富,大量业务代码用了 proprietary 的语法,比如 PIVOT/UNPIVOT、CTE、IDENTITY 的实现方式、sequence 的差异、临时表和表变量的行为差异等。
建议的做法是:先用 如金仓的KDMS之类的迁移评估工具做一轮自动扫描,它能把一部分语法做自动转换,但剩余的手动工作量往往比预期大。我的经验是,自动化工具大概能覆盖 60%~70% 的语法转换,剩下的 30%~40% 需要人工介入。这部分工作量在项目排期时很容易被低估。
数据类型差异要特别关注。 SQL Server 的 datetime2、time、datetimeoffset 等数据类型在金仓里的对应关系要搞清楚,特别是精度问题。另外,SQL Server 的 uniqueidentifier(GUID)在金仓里如何映射,以及排序规则(Collation)的处理,都是需要注意的点。
存储过程和函数的改写是另一块硬骨头。 如果业务逻辑重度依赖 SQL Server 的 stored procedure,改写工作量不亚于重写。这里没有捷径,只有老老实实逐个审查。
信创迁移的时间窗口通常非常紧,但越是这种时候越要清醒。很多信创迁移项目的失败,不是在技术上做不到,而是因为时间压力导致质量把控不到位。 语法改写不完整就上线、测试覆盖不足就切正式库——这些问题在信创项目里我见过不少。
如果你正在规划或参与这样的迁移,建议在项目前期就把「兼容性改写」和「充分测试」的时间单独列出来,不要让这两块被其他工作挤占。迁移工具能加速,但替代不了人仔细审核每一条业务逻辑。
SQL Server 迁移表面上是一项数据库技术工作,实际上是一项系统性工程。它考验的不只是 DBA 的技术能力,更考验项目管理能力、跨团队沟通能力,以及对业务系统整体的理解。
最后说一句:很多坑不是技术问题,是人的问题。迁移方案定了,开发团队说「我们没问题」,测试团队说「我们测完了」,结果上线后问题一堆——不是因为技术不过关,而是因为没有人真正负责端到端的验证。找一个明确的 migration owner,这个人要对整个迁移负责到底。这是所有注意事项里,最务实的一条。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。