如何通过Terraform将Basic Azure SQL数据库迁移至vCore且不丢失数据?
Azure SQL从Basic SKU迁移到vCore版本(无数据丢失)的Terraform方案
核心问题分析
直接修改sku_name从"Basic"切换到"GP_Gen5_4"会触发Terraform销毁旧库再重建新库——这是因为Basic属于DTU层级,vCore属于独立的SKU体系,Terraform的azurerm_mssql_db资源跨层级变更时默认会执行重建操作。要避免数据丢失,需要结合Azure原生在线升级能力和Terraform状态管理分步骤操作。
最优迁移方案
1. 先通过Azure原生工具完成在线SKU升级(不修改Terraform配置)
Azure支持DTU到vCore的在线原地升级,过程中不会删除数据库,数据完整保留,且停机时间极短(毫秒级):
- 使用Azure CLI执行升级命令:
az sql db update --resource-group <你的资源组名称> --server <SQL服务器名称> --name <目标数据库名称> --sku-name GP_Gen5_4
也可以直接在Azure门户的数据库配置页面手动切换SKU到GP_Gen5_4。
2. 同步Terraform配置与实际资源状态
升级完成后,Terraform本地状态文件仍记录旧的Basic SKU,需要同步状态并更新配置:
- 执行
terraform refresh命令,拉取Azure上的实际资源状态更新到本地状态文件,让Terraform识别到sku_name已变更为GP_Gen5_4。 - 修改Terraform配置中的
sku_name为"GP_Gen5_4",同时调整vCore专属参数(比如Basic层级无效的min_capacity需匹配SKU规格):
module "mssql_api_db" { depends_on = [module.mssql_server] source = "app.terraform.io/xxx/mssql_db/azurerm" version = "2.0.0" name = local.api_database_name server_id = module.mssql_server.mssql_server_id use_elastic_pool = false collation = "SQL_Latin1_General_CP1_CI_AS" max_size_gb = var.api_infra_db_size_gb min_capacity = 4 # 匹配GP_Gen5_4的vCore数量 read_replica_count = 0 read_scale = false zone_redundant = false sku_name = "GP_Gen5_4" }
- 执行
terraform plan验证,此时应显示No changes. Your infrastructure matches the configuration.,说明配置与状态已完全同步。
备选方案:尝试用Terraform lifecycle块阻止重建(不推荐)
如果要直接通过Terraform变更,可尝试添加lifecycle块强制阻止销毁重建,但需注意:跨SKU层级的变更可能不被Terraform资源提供者完全支持,易出现状态不一致问题。示例配置:
module "mssql_api_db" { # 原有配置... sku_name = "GP_Gen5_4" lifecycle { prevent_destroy = true } }
该方案风险较高,仅在无法使用原生升级时尝试,优先推荐第一种分步方案。
关键注意事项
- 升级前务必执行全量备份,应对意外情况:
az sql db backup create --resource-group <资源组名> --server <服务器名> --database <数据库名> --backup-type full
- 选择低峰期执行升级,减少对业务的潜在影响。
- 同步状态后,后续的数据库配置变更可正常通过Terraform管理,不会再触发重建。
内容的提问来源于stack exchange,提问作者Kalle
相关产品推荐
相关产品推荐

