无法使用Azure SQL Elastic Sc​​ale删除分片映射

Cra*_* W. 5 c# azure-elastic-scale azure-sql-database azure-elastic-sharding

我们的系统中有一个称为"身份计划"的实体.这也是我们的分片边界,每个身份程序都存储在自己的分片中,因此分片的标识符是身份程序的标识符.

我们正在实施物理删除身份程序的能力.作为该过程的一部分,我们希望清理分片图.为此,我写了以下内容:

var shardKey = new Guid("E03F1DC0-5CA9-45AE-B6EC-0C90529C0062");

var connectionString = @"shard-catalog-connection-string";
var shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(connectionString, ShardMapManagerLoadPolicy.Lazy);
var shardMap = shardMapManager.GetListShardMap<Guid>("IdentityProgramIdListShardMap");

if (shardMap.TryGetMappingForKey(shardKey, out PointMapping<Guid> mapping))
{
    if (mapping.Status == MappingStatus.Online)
    {
        shardMap.MarkMappingOffline(mapping);
    }

    shardMap.DeleteMapping(mapping);
}
Run Code Online (Sandbox Code Playgroud)

问题是当它遇到DeleteMapping调用时会出现异常:

ShardManagementException:在分片映射'IdentityProgramIdListShardMap'中引用shard'[shard-connection-string]'的映射不存在.执行存储过程'__ShardManagement.spBulkOperationShardMappingsGlobalBegin'以执行操作'RemovePointMapping'时发生错误.如果另一个并发用户已经删除了映射,则会发生这种情况.

但是映射还没有被删除,因为在那之后我执行:

mappings = shardMap.GetMappings();
foreach(var mapping in mappings)
{
    Console.WriteLine(mapping.Value);
}
Run Code Online (Sandbox Code Playgroud)

我可以看到shardmap条目仍然存在,并标记为脱机.

如果我删除了对MarkMappingOffline我的调用,我会得到一个异常,说明无法删除分片映射,因为它是在线的.

所以我似乎有一个捕获22.如果我将其标记为脱机,则认为分片映射已消失,并且不允许我将其删除.如果我没有将其标记为离线,则告诉我它必须处于脱机状态.

Jar*_*ore 6

您必须始终对当前版本的映射进行操作,因此您应该编写代码

if (shardMap.TryGetMappingForKey(shardKey, out PointMapping<Guid> mapping))
{
    if (mapping.Status == MappingStatus.Online)
    {
        // `mapping =` on next line is needed
        mapping = shardMap.MarkMappingOffline(mapping);
    }

    shardMap.DeleteMapping(mapping);
}
Run Code Online (Sandbox Code Playgroud)

为了进一步解释:弹性数据库工具使用乐观并发模型,其中每个操作都会检查您是否在每个对象的最新版本上运行.错误消息是说映射存在"并发"修改,即在您获得映射之后但在执行DeleteMapping之前,其他人同时执行了MarkMappingOffline.实际上"其他人"是你自己,但是由于你没有删除最新版本的映射,弹性数据库工具并不知道它就是你.:)