如何在不使用Bacpac或离线的情况下修改Azure SQL数据库排序规则
无需Bacpac的Azure SQL数据库排序规则变更方案
针对500G生产库无法接受长时间停机的场景,以下是两种可行的在线/低停机方案:
方案一:逐步修改数据库及对象排序规则(低停机,在线操作)
这种方案无需额外创建数据库,直接在生产库上分批修改,适合能接受短暂小范围锁表的场景。
修改数据库默认排序规则
首先执行语句更新数据库的默认排序规则,这一步耗时极短,仅影响后续新建的对象:ALTER DATABASE [YourProductionDB] COLLATE Latin1_General_100_CI_AS_SC_UTF8;生成对象修改脚本
现有表的字符列(char/varchar/nchar/nvarchar)、索引、存储过程等仍使用旧排序规则,需批量生成修改脚本:- 生成列排序规则修改脚本:
SELECT 'ALTER TABLE [' + SCHEMA_NAME(t.schema_id) + '].[' + t.name + '] ALTER COLUMN [' + c.name + '] ' + ty.name + '(' + CASE WHEN ty.max_length = -1 THEN 'MAX' ELSE CAST(ty.max_length AS VARCHAR) END + ') ' + 'COLLATE Latin1_General_100_CI_AS_SC_UTF8 ' + CASE WHEN c.is_nullable = 1 THEN 'NULL' ELSE 'NOT NULL' END + ';' FROM sys.columns c JOIN sys.tables t ON c.object_id = t.object_id JOIN sys.types ty ON c.system_type_id = ty.system_type_id AND c.user_type_id = ty.user_type_id WHERE c.collation_name = 'SQL_Latin1_General_CP1_CI_AS' AND ty.name IN ('char', 'varchar', 'nchar', 'nvarchar'); - 对于索引、触发器、外键等依赖对象,需先删除再重建(可通过SSMS的"生成脚本"功能导出重建脚本,修改排序规则后执行)。
- 生成列排序规则修改脚本:
分批执行修改
- 选择业务低峰期,每次仅处理少量表/列,避免长时间锁表;
- 用事务包裹单表的修改操作,确保原子性;
- 大型表可采用"新建表+分批迁移+切换表名"的方式:
- 创建与原表结构一致但排序规则正确的新表;
- 按主键范围分批将原表数据插入新表;
- 低峰期停止原表写入,同步最后一批数据,执行
sp_rename交换原表与新表名称,再重建依赖对象。
方案二:利用Azure DMS实现近乎零停机迁移
这种方案通过在线迁移工具将数据同步到预配置好目标排序规则的新数据库,停机时间仅为切换连接的几分钟。
创建目标数据库
在Azure门户创建新的Azure SQL数据库,指定排序规则为Latin1_General_100_CI_AS_SC_UTF8,配置与生产库一致的服务层级和资源。配置Azure DMS在线迁移
- 新建Azure Database Migration Service实例;
- 创建迁移项目,选择源为生产Azure SQL数据库,目标为新创建的数据库;
- 选择"在线迁移"模式,启动全量数据同步,之后DMS会持续同步生产库的增量变更。
切换业务连接
- 监控增量同步延迟,当延迟接近0时,在业务低峰期:
- 临时停止应用对生产库的写入操作;
- 等待DMS完成最后一次增量同步;
- 将应用连接字符串切换为目标数据库;
- 恢复应用写入,验证业务正常后,可删除原生产库。
- 监控增量同步延迟,当延迟接近0时,在业务低峰期:
关于Azure复制的可行性说明
Azure SQL的主动地理复制无法直接用于修改排序规则,因为副本的排序规则必须与主库完全一致。但可结合副本做间接操作:
- 将生产库配置为主动地理复制主库,创建只读副本;
- 将只读副本转换为独立数据库(此时排序规则仍为旧值);
- 在独立数据库上执行方案一的修改步骤,完成后将应用切换到该库。
不过这种方法的缺点是,从副本转成独立库后,主库的新变更无法同步,因此需要在转换前停止写入,或结合DMS同步增量,整体停机时间比方案二长。
内容的提问来源于stack exchange,提问作者dbdownunder
相关产品推荐
相关产品推荐

