Azure 弹性数据库合并 GUI 密钥碎片

Azure Elastic Database Merge GUI Key Shards

在 Azure 中,我们有四个碎片,我想删除其中两个,因为我们不再需要它们了。数据应合并到其他两个分片中。

我使用带有 GUID 作为键的列表映射来识别分片(在我们的应用程序中这是 UserId)。 在教程中,我只找到了将 Shards 与 Range 类型合并的示例。 有没有办法以更快的方式合并这些类型的碎片,或者我必须为此编写自己的工具?

如果合并是自动执行的,例如在以下情况下会发生什么: 用于识别分片的 GUID 是 UserId,现在该数据已从分片 A 移动到分片 B。还有另一个 Table 称为 Comments,其 UserId 作为 ForeignKey。 Table 中的 PrimaryKey 是一个经典的数字自动增量值。如果将这些值从分片 A 移动到分片 B,它们会发生什么变化?它们会被插入并为其分配一个新 ID 还是根本不起作用?

还有一些本地 FileStorage invloved,它在路径中使用 ID,所以我认为无论如何我都必须编写自己的工具。

为此,我查看了 ShardMapManager,但没有完全理解它是如何工作的。在 ShardMappingsGlobal Table 中有一个名为 MappingId 的列。但这不是存储在分片数据库中的 Guid/UserId。我如何获得用于识别分片的实际 Guid,在我的例子中是 UserId? 我也没有找到在碎片之间移动数据的方法。 我现在要做的是自己用工具在碎片之间传输数据,然后使用 ListShardMap.UpdateMapping 方法为该值设置一个新的碎片。 在操作结束时,我会使用 ListShardMap.DeleteShard 或者有更好的方法吗?

编辑:

我编写了自己的工具来合并碎片,但我现在遇到一个奇怪的异常。这里有一些代码:

        Guid userKey = Guid.Parse(userId);
        ListShardMap<Guid> map = GetUserShardMap<Guid>();

        try
        {
            PointMapping<Guid> currentMapping = map.GetMappingForKey(userKey);

            PointMapping<Guid> mappingOffline = map.UpdateMapping(currentMapping, new PointMappingUpdate()
            {
                Status = MappingStatus.Offline
            });  
         }

UpdateMapping 导致以下异常:

存储错误:错误 515,级别 16,状态 2,过程 __ShardManagement.spBulkOperationShardMappingsLocal,第 98 行,消息:无法将值 NULL 插入列 'LockOwnerId',table __ShardManagement.ShardMappingsLocal

我不明白为什么还要插入?我检查了本地和全局 Shardmapping tables 中的 mappingId,映射就在那里,所以我认为不需要插入。我还在这里查看了提到的存储过程 spBulkOperationShardMappingsLocal 的代码:https://github.com/Azure/elastic-db-tools/blob/master/Src/ElasticScale.Client/ShardManagement/Scripts/UpgradeShardMapManagerLocalFrom1.1To1.2.sql 在 Insert 语句中,LockOwnerId 未作为参数传递,因此它只能失败。 目前我使用测试设置,因为我当然不想在生产系统上玩。也许我在那里犯了一个错误,但对我来说一切看起来都很好。对于有关此错误的任何提示,我将不胜感激。

In the tutorials i only found samples to merge Shards with the Range type. Is there a way to merge these type of shards in a faster way or do i have to write my own tool for this?

是的,Split-Merge tool 可以从范围和列表分片映射中移动数据。对于列表分片映射,您可以为每个键发出 shardlet 移动请求。不幸的是,Split-Merge 工具的设置有些复杂,上次我花了大约一个小时来配置。我知道这不是很好,我会留给您来决定是否需要更多或更少的时间来编写您自己的自定义版本。

There is another Table called Comments which has the UserId as ForeignKey. The PrimaryKey in this Table is a classic numeric auto increment value. What will happen to those values if they are moved from Shard A to Shard B? Will they be inserted and a new ID is assigned to them or will this not work at all?

自动增量列的值不会被复制过来,它们将在目的地重新生成。因此,新的 ID 将分配给这些行。

For that I took a look at the ShardMapManager but did not fully understand how it works. In the ShardMappingsGlobal Table is a Column called MappingId. But this is not the Guid/UserId which is stored in the Shard Database. How do i get the actual Guid which is used to identify the shard, in my case the UserId?

强烈建议不要尝试自己编辑 ShardMapManager 表,这很容易搞砸。编辑 ShardMapManager 表正是 Elastic Database Tools library 的设计目的。

您可以使用 ListShardMap.UpdatePointMapping method 更新映射的 元数据 。需要明确的是,这只会更新 ShardMapManager 表对数据 应该 所在位置的了解。实际上移动映射必须由更高层来完成。

这是对 Split-Merge 服务功能的高级总结:

  1. 锁定映射以防止来自另一个分片映射管理操作的并发更新
  2. 使用 ListShardMap.UpdatePointMapping 将映射标记为离线。这可以防止使用 OpenConnectionForKey 的数据导向路由被允许使用该密钥访问数据。它还会终止分片上的所有当前会话以强制它们重新连接,这确保没有活动连接在使用 now-offline key
  3. 对数据进行操作
  4. 移动底层数据,使用Shard Map的SchemaInfo来判断哪些表需要移动
  5. 更新映射并在线标记ListShardMap.UpdatePointMapping
  6. 解锁映射