如何使用实体组事务清除 WADLogs 表时处理"指定的资源不存在"异常



我们需要定期清除Azure WADLogs表。我们通过使用实体组事务删除超过15天的记录来实现这一点。逻辑是这样的。

bool recordDoesNotExistExceptionOccured = false;
CloudTable wadLogsTable = tableClient.GetTableReference(WADLogsTableName);
partitionKey = "0" + DateTime.UtcNow.AddDays(noOfDays).Ticks;
TableQuery<WadLogsEntity> buildQuery = new TableQuery<WadLogsEntity>().Where(
                            TableQuery.GenerateFilterCondition("PartitionKey",                
                            QueryComparisons.LessThanOrEqual, partitionKey));
while (!recordDoesNotExistExceptionOccured)
{
    IEnumerable<WadLogsEntity> result = wadLogsTable.ExecuteQuery(buildQuery).Take(1000);
    //// Batch entity delete.
    if (result != null && result.Count() > 0)
    {
         Dictionary<string, TableBatchOperation> batches = new Dictionary<string, TableBatchOperation>();
         foreach (var entity in result)
         {
             TableOperation tableOperation = TableOperation.Delete(entity);
             if (!batches.ContainsKey(entity.PartitionKey))
             {
                 batches.Add(entity.PartitionKey, new TableBatchOperation());
             }
             // A Batch Operation allows a maximum 100 entities in the batch which must share the same PartitionKey.                        
             if (batches[entity.PartitionKey].Count < 100)
             {
                 batches[entity.PartitionKey].Add(tableOperation);
             }
        }
        // Execute batches.
        foreach (var batch in batches.Values)
        {
            try
            {
                await wadLogsTable.ExecuteBatchAsync(batch);
            }
            catch (Exception exception)
            {
                // Log exception here.
                // Set flag.
                if (exception.Message.Contains(ResourceDoesNotExist))
                {
                    recordDoesNotExistExceptionOccured = true;
                }
                break;
            }
        }
    }
    else
    {                            
        break;
    }
}

我的问题是:

  1. 这是清除WADLogs表的有效方法吗?如果没有,还有什么能让情况变得更好
  2. 这是处理"指定资源不存在异常"的正确方法吗?如果没有,我该如何做得更好
  3. 这种逻辑在任何特定情况下都会失败吗
  4. 如果此代码位于部署了多个实例的工作程序中,这种方法将如何改变

我参考了这里给出的解决方案,得出了这个代码。

  1. 如果不能直接删除整个表,那么批处理通常是清除表的一部分的最佳方式。然而,在上面的代码中有一些细节问题,我将在下面概述。

  2. 我不知道为什么在查询中刚刚返回的表实体中会出现此错误,除非您在另一个线程上从该表中删除内容。但是,在您给出的场景中,当出现错误时,您应该而不是停止整个过程。假设您有1000个结果要删除。第二个已经被另一个线程删除,当你再次尝试删除它时返回了一个错误-现在你错过了删除所有其他实体,包括该批中的其他实体,因为批是原子的!要修复这种情况,我建议从批处理中删除失败的实体(错误消息将包括其索引),重试该批处理,然后继续删除其余批处理。

  3. 参见2。此外,如果有100多个实体具有相同的分区键,则不会立即删除其余实体,而是忽略它们,并在下一次循环迭代中删除它们。如果有许多条目具有相同的分区键,这可能会导致大量额外的查询,因此将它们添加到新批中可能会更高效。

  4. 一旦有更多的工作人员参与,2中的问题将在当前设计中变得更糟,因为您总是查询前1000个。现在,您将有多个线程下载相同的结果,并试图删除相同的内容。在当前的设计中,这将导致许多错误,因为工作人员将删除相同的结果。我看到的最简单的解决方案是找到一种更好的方法来划分工作,而不会造成重叠。一个想法可能是让每个工作人员花不同的时间删除,这也会带来优化必须发送的批次数量的额外好处。当然,还有许多其他有效的策略。

最新更新