4. 源与目标环境盘点
迁移升级项目真正开始动手之前,最容易被低估、却最决定成败的一步,是源环境与目标环境的全面盘点。很多迁移事故并非发生在数据搬运阶段,而是发生在“我们以为已经知道源库有什么”的阶段:某个被遗忘的链接服务器、一个依赖 CLR 程序集的存储过程、一个每天凌晨跑批的 SQL Agent 作业、一个用 SQL 登录而非 Windows 登录的应用账号,都可能在切换后集中爆发。盘点的目标不是罗列清单,而是建立一张可迁移性地图:哪些对象能直接搬、哪些需要改写、哪些依赖外部资源、哪些必须重新配置。
盘点对象的分层结构
建议按“实例层 → 数据库层 → 对象层 → 依赖层 → 外围层 → 安全层”六个层次推进,每一层都有明确的采集手段和判断标准。
实例层关注版本、版本号、补丁级别、排序规则、实例级配置。核心命令是 SELECT @@VERSION 与 SERVERPROPERTY,重点看 ProductVersion、ProductLevel、Edition、Collation、IsClustered、IsHadrEnabled。排序规则尤其关键:如果源实例是 Chinese_PRC_CI_AS,目标实例却是 SQL_Latin1_General_CP1_CI_AS,跨实例的临时表连接、字符串比较都可能出现不一致。实例级配置还包括 max server memory、max degree of parallelism、cost threshold for parallelism、backup compression default 等,这些参数在目标环境需要重新评估,而不是照搬。
数据库层要采集数据库清单、恢复模式、兼容级别、大小、文件布局、是否启用 CDC/变更跟踪/Service Broker、是否参与镜像或可用性组。兼容级别是升级的核心变量:从 SQL Server 2016 的 130 升到 2022 的 160,兼容级别可以暂时保留,但必须评估 sys.dm_db_persisted_sku_features 和已弃用功能。数据库大小与文件布局决定迁移窗口:一个 2TB 的库用备份还原可能需要数小时,而用日志传送或 AlwaysOn 做预同步则可以把停机窗口压缩到分钟级。
对象层是盘点中最细碎的部分。表、视图、存储过程、函数、触发器、索引、约束、同义词、序列、用户定义类型、CLR 对象、全文索引、分区方案与分区函数,都要逐一登记。对象数量可以用系统视图快速统计:
SELECT type_desc, COUNT(*) AS cnt
FROM sys.objects
WHERE is_ms_shipped = 0
GROUP BY type_desc
ORDER BY cnt DESC;
但数量只是起点,真正需要标记的是风险对象:使用了已弃用语法(如 SET ROWCOUNT、旧式 *= 外连接)、依赖 xp_cmdshell、依赖特定排序规则、使用了 TEXT/NTEXT/IMAGE 旧数据类型、包含跨库三部分命名引用的对象。这些对象在目标环境往往需要改写或额外授权。
依赖关系:盘点的真正难点
对象之间的依赖关系决定了迁移顺序和影响范围。SQL Server 提供 sys.sql_expression_dependencies 来追踪对象级依赖,但它对动态 SQL、跨库引用和 CLR 的覆盖有限。实际盘点中,建议把依赖分为四类:
- 库内依赖:视图依赖表、存储过程依赖视图、函数被计算列引用。这类依赖可以通过脚本按依赖顺序生成,通常可控。
- 跨库依赖:存储过程中出现
OtherDB.dbo.Table三部分命名。迁移时如果目标实例的库名或实例名变化,必须改写或建立同义词。 - 跨实例依赖:通过链接服务器访问远程数据。这类依赖在目标环境需要重建链接服务器、重新配置安全映射,并验证网络连通性。
- 外部依赖:CLR 程序集、外部表、PolyBase、机器学习服务、文件表。这些依赖操作系统和实例级功能,迁移前必须确认目标环境已启用对应特性。
一个实用的做法是先用 sys.sql_modules 做文本扫描,找出所有包含三部分命名和 OPENQUERY、OPENDATASOURCE 的对象,再结合 sys.sql_expression_dependencies 做交叉验证。对于动态 SQL 拼接的依赖,文本扫描是唯一可靠手段。
外围应用、作业与链接服务器
外围应用是“数据库之外但属于同一业务系统”的部分,包括 SSIS 包、SSRS 报表、SSAS 多维/表格模型、Power BI 数据集、外部应用程序连接串、ODBC/JDBC 驱动版本。盘点时要记录每个外围应用连接的数据库、使用的账号、连接方式(Windows 集成或 SQL 登录)、是否使用加密连接。SSIS 包尤其要注意:包中可能硬编码了源服务器名,迁移后需要重新配置连接管理器。
SQL Agent 作业是另一个高频遗漏点。作业不仅包含 T-SQL 步骤,还可能包含 SSIS 步骤、PowerShell 步骤、操作系统命令步骤、复制步骤。盘点时要采集作业名称、步骤类型、调度计划、目标数据库、运行账号、是否启用、历史执行结果。可以用以下查询快速导出:
SELECT j.name AS job_name, j.enabled, s.step_id,
s.subsystem, s.database_name, s.command
FROM msdb.dbo.sysjobs j
JOIN msdb.dbo.sysjobsteps s ON j.job_id = s.job_id
ORDER BY j.name, s.step_id;
链接服务器盘点要记录名称、提供程序、数据源、产品名、访问接口、安全映射方式(sp_addlinkedsrvlogin 的 useself 设置)。如果源环境使用 useself = true 依赖 Kerberos 委派,目标环境必须确认 SPN 和委派配置是否同步迁移。
安全主体:最容易被“看起来没问题”掩盖的部分
安全主体包括登录名、数据库用户、角色、架构、权限、证书、非对称密钥、凭据、审核。迁移时常见的问题是:登录名在目标实例不存在,导致数据库用户成为“孤立用户”;或者登录名存在但 SID 不同,权限映射错乱。盘点时要采集登录名类型(SQL 登录/Windows 登录/证书/非对称密钥)、SID、默认数据库、是否启用、服务器角色成员资格。数据库用户要采集对应的登录名、默认架构、数据库角色成员资格、显式权限。
对于 SQL 登录,密码无法直接导出,迁移时需要重新设置或使用 sp_help_revlogin 类脚本保留 SID 和密码哈希。对于 Windows 登录,要确认目标域或信任关系是否可达。对于包含 EXECUTE AS 或签名模块的对象,证书和非对称密钥必须一并迁移,否则模块签名失效。
源与目标环境盘点的关系视图
下面的 SVG 用一张关系图把六层盘点对象、它们之间的依赖方向以及迁移时的处理动作组织在一起,帮助在动手前建立整体判断。
这张图强调一个判断:依赖层是源与目标之间真正的“桥”,它把对象层、外围层和安全层串在一起。盘点时如果只登记对象清单而不追踪依赖,迁移脚本很可能因为执行顺序错误或外部引用缺失而失败。实际项目中,建议把依赖清单与对象登记表合并维护,每标记一个高风险依赖,就同步确定改写方案、验证方法和回退策略。
最后需要提醒的是,盘点不是一次性动作。源环境在迁移窗口前仍可能发生变化:新增作业、修改存储过程、调整权限。因此在正式切换前 24 小时内,应再做一次增量比对,重点检查对象数量、作业调度、登录名和链接服务器的变化。只有把“静态清单”变成“可复核的基线”,盘点才真正为迁移升级提供了可靠依据。