Невозможно удалить сопоставление сегментов с помощью эластичной шкалы SQL Azure.

У нас есть объект в нашей системе, называемый "программа идентификации". Это также наша граница сегментирования, каждая идентификационная программа хранится в своем собственном фрагменте, поэтому идентификатор сегмента является идентификатором программы идентификации.

Мы находимся в процессе реализации возможности физического удаления программы идентификации. В рамках этого процесса мы хотим очистить карту осколков. Для этого я написал следующее:

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);
}

Проблема в том, что когда он попадает в DeleteMapping вызов это получает исключение:

ShardManagementException: сопоставление ссылающегося шарда '[shard-connection-string]' в карте шардов 'IdentityProgramIdListShardMap' не существует. Произошла ошибка при выполнении хранимой процедуры "__ShardManagement.spBulkOperationShardMappingsGlobalBegin" для операции "RemovePointMapping". Это может произойти, если другой одновременный пользователь уже удалил сопоставление.

Но отображение не было удалено, потому что сразу после этого я выполняю:

mappings = shardMap.GetMappings();
foreach(var mapping in mappings)
{
    Console.WriteLine(mapping.Value);
}

И я вижу, что запись shardmap все еще там и помечена как Offline.

Если я удалю звонок MarkMappingOffline Я получаю исключение, утверждающее, что сопоставление осколка не может быть удалено, поскольку оно находится в сети.

Так что у меня вроде есть уловка-22. Если я отмечаю его как офлайн, он думает, что сопоставление осколков исчезло, и не позволит мне удалить его. Если я не отмечу его как офлайн, он говорит, что он должен быть офлайн.

1 ответ

Решение

Вы всегда должны работать с текущей версией сопоставления, поэтому ваш код должен быть

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);
}

Чтобы объяснить немного подробнее: инструменты эластичного БД используют оптимистическую модель параллелизма, где каждая операция проверяет, что вы работаете с последней версией каждого объекта. В сообщении об ошибке говорится, что в сопоставлении произошла "одновременная" модификация, т.е. кто-то еще одновременно сделал MarkMappingOffline после того, как вы получили сопоставление, но до того, как вы сделали DeleteMapping. На самом деле этим "другим человеком" был вы сами, но поскольку вы не удаляли последнюю версию отображения, инструменты эластичного БД не знали, что это вы.:)

Другие вопросы по тегам