5

我們的系統中有一個名爲「身份程序」的實體。這也是我們的分片邊界,每個身份程序都存儲在它自己的分片中,所以分片的標識符就是身份程序的標識符。使用Azure SQL Elastic Sc​​ale無法刪除分片映射

我們正在實施物理刪除身份程序的能力。作爲該過程的一部分,我們要清理碎片映射。要做到這一點,我寫了下面的:

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:映射引用碎片「[碎片連接字符串]'在分片映射'IdentityProgramIdListShardMap'中不存在。執行存儲過程'__ShardManagement.spBulkOperationShardMappingsGlobalBegin'時發生錯誤,以執行'RemovePointMapping'操作。如果另一個併發用戶已經刪除了映射,則會發生這種情況。

但映射沒有被刪除,因爲之後我執行:

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

而且我可以看到shardmap入口仍然存在,並被標記爲脫機。

如果我刪除了對MarkMappingOffline的調用,我收到一個異常,指出由於它在線而無法刪除分片映射。

所以我似乎有一個趕上22。如果我將它標記爲離線,它認爲分片映射消失了,不會讓我刪除它。如果我不將它標記爲脫機,它會告訴我它必須脫機。

回答

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

爲了解釋遠一點:彈性數據庫工具使用這裏您在操作上的每個操作檢查樂觀併發模型每個對象的最新版本。該錯誤消息說,映射有一個「併發」修改,即有人在獲得映射之後但在執行DeleteMapping之前同時做了MarkMappingOffline。實際上,「其他人」是你自己,但是因爲你沒有刪除映射的最新版本,彈性數據庫工具並不知道它是你。 :)

+0

感謝您的解釋。在我發佈這個問題後,我實際上已經想到了這一點,這就是爲什麼我沒有回過頭來標記答案。我(錯誤地)認爲'shardMap.MarkMappingOffline(mapping);'會簡單地修改傳入的映射,而不是返回一個新的/修改過的實例。現在都在工作。 –

+0

任何方式使用Powershell來做到這一點? – Deepak