用途:判断一次架构变更能否安全应用到在线 Azure SQL Database,并在不安全时改写迁移脚本。适用于项目发布、流水线步骤、ORM 迁移或手写脚本等任何迁移途径。
主要能力与要点:
- 区分元数据级与重写级 ALTER。NOT NULL 列加运行时常量默认值(如 SYSUTCDATETIME())只写少量日志;NEWID() 默认值、int 转 bigint、varchar 转 nvarchar、varchar 转 varchar(max)、NULL 转 NOT NULL 会重写全表并写大量日志。max/LOB 类型及行超过 8060 字节的列无法在线执行。
- 锁与排队。ALTER TABLE 全程持有 Sch-M 锁,与包括普通 SELECT 在内的所有锁模式不兼容;快照隔离和 NOLOCK 都无法避免等待。一个 2 毫秒的变更可能因前方长查询而阻塞后续查询数秒。
- 关键设置。WITH (ONLINE = ON) 可用于 ALTER COLUMN、ALTER TABLE REBUILD、CREATE INDEX、ALTER INDEX REBUILD,但在 ADD/DROP COLUMN 上是语法错误,且列被索引或默认约束引用时会被拒绝。ELEVATE_ONLINE 可设为 WHEN_SUPPORTED 或 FAIL_UNSUPPORTED,仅作用于未显式声明 ONLINE 的语句。SET LOCK_TIMEOUT 可限制等待,但 Msg 1222 不会回滚事务,需配合 SET XACT_ABORT ON。WAIT_AT_LOW_PRIORITY 仅用于重建,不能与在线 ALTER COLUMN 同用;RESUMABLE = ON 需 ONLINE = ON,且不能在显式事务内运行。
- expand-contract。扩展阶段只新增、不改名,用可空列或运行时常量默认值;回填分批在独立部署中进行;收缩阶段在旧代码全部下线后再删除旧结构。不要原地重命名,sp_rename 只给严重级别 10 的提示信息。
- 不要在应用启动时迁移。并发启动时 IF NOT EXISTS 守卫无法防止重复回填,需用 sp_getapplock 串行化。
- 重试风险。可重试单元可能执行多次,要么整个迁移放在一个事务中,要么每条语句(含数据语句)都幂等。
- 幂等语法。Azure SQL Database 不支持 CREATE TABLE IF NOT EXISTS、CREATE INDEX IF NOT EXISTS、ADD IF NOT EXISTS;支持 DROP COLUMN IF EXISTS、DROP CONSTRAINT IF EXISTS、DROP TABLE IF EXISTS、CREATE OR ALTER VIEW。需置于批首的语句可放入 sp_executesql。
- 回滚即前向迁移。DROP COLUMN 只改元数据,空间不回收;反向语句往往同样昂贵甚至失败。
验证方式:用 sqlcmd 加 -m-1 运行迁移,检查退出码与输出中是否出现 Msg 或 Caution 行;再用查询核对迁移历史、未回填行、@@TRANCOUNT 与 sys.index_resumable_operations。
限制:资料基于特定引擎版本与兼容级别测量,具体行为随环境而异;未提供收费、平台支持范围等信息。