如何在SQL Server中删除分片映射及分片库以清理租户资源?
彻底删除租户专属数据库及相关引用的正确方法
先说说你现有代码的问题
你的代码只走完了分片映射的逻辑删除流程(标记离线、删映射、删分片记录),但没实际删除数据库本身,还可能有两个疏漏:
- 没显式刷新分片映射管理器的缓存(Lazy加载模式下,本地缓存可能没同步数据库的修改,导致你看
ShardsGlobal表还以为映射没删) - 缺少删除数据库的关键步骤
完整的删除流程(适配Azure弹性池)
第一步:修复分片映射的删除逻辑,确保记录真正清除
先修改现有代码,加上缓存刷新,保证ShardsGlobal里的映射被彻底删掉:
string shardMapManagerConnectionString = configuration.GetShardMapMangerConnectionString(); ShardMapManager shardMapManager; shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager( shardMapManagerConnectionString, ShardMapManagerLoadPolicy.Lazy); var shardMap = shardMapManager.GetListShardMap<T>(configuration.ShardMapName); if (shardMap.TryGetMappingForKey(key, out PointMapping<T> mapping)) { // 标记映射离线(如果当前是在线状态) if (mapping.Status == MappingStatus.Online) { mapping = shardMap.MarkMappingOffline(mapping); } // 删除映射记录 shardMap.DeleteMapping(mapping); // 删除分片记录 var shard = shardMap.GetShard(mapping.Shard.Location); shardMap.DeleteShard(shard); // 刷新缓存,强制同步数据库的修改 shardMapManager.RefreshShardMap(shardMap); }
第二步:实际删除租户数据库(Azure弹性池专用)
分片映射的记录清完后,必须单独执行删除数据库的命令。注意Azure弹性池里删库要先杀掉所有活跃连接,不然会失败:
// 从映射里拿租户数据库的服务器和名称,拼接连接字符串 var shardLocation = mapping.Shard.Location; string tenantDbConnStr = $"Server={shardLocation.DataSource};Database={shardLocation.DatabaseName};Authentication=Active Directory Default;"; using (var conn = new SqlConnection(tenantDbConnStr)) { conn.Open(); // 先杀掉这个数据库的所有活跃连接 var killSessionsCmd = new SqlCommand(@" DECLARE @killCmd VARCHAR(8000) = ''; SELECT @killCmd = @killCmd + 'KILL ' + CAST(session_id AS VARCHAR(5)) + ';' FROM sys.dm_exec_sessions WHERE database_id = DB_ID(@dbName); EXEC(@killCmd); ", conn); killSessionsCmd.Parameters.AddWithValue("@dbName", shardLocation.DatabaseName); killSessionsCmd.ExecuteNonQuery(); // 执行删库命令 var dropDbCmd = new SqlCommand($"DROP DATABASE [{shardLocation.DatabaseName}];", conn); dropDbCmd.ExecuteNonQuery(); }
第三步:验证清理结果
- 查Shard Map Manager的
ShardsGlobal和MappingsGlobal表,确认对应记录已经消失 - 登Azure门户看弹性池,确认租户数据库被移除
- 用原租户键尝试获取映射,应该返回不存在
生产环境注意事项
- 权限:执行操作的账号必须有
ALTER ANY DATABASE权限,Azure里得是SQL Server管理员或者有对应权限的AD账号 - 事务:建议把分片映射修改和删库操作包在事务里,避免出现映射删了但数据库没删的半吊子状态
- 备份:删库前务必确认已经完成必要的备份,生产环境别手抖
内容的提问来源于stack exchange,提问作者Patola
相关产品推荐
相关产品推荐

