诊断和排查 Azure Cosmos DB 的“未找到”异常

适用范围: NoSQL

HTTP 状态代码 404 表示资源不再存在。

预期行为

应用程序预期接收代码 404 并正确进行处理的有效方案有许多。

对应该存在或确实存在的项返回了“未找到”异常

以下是在该项应该或确实存在的情况下返回状态代码 404 的可能原因。

读取会话不可用于输入会话令牌

解决方案

  1. 将当前 SDK 更新到已发布的最新版本。 此特定错误的最常见原因问题已在最新版 SDK 中得到解决。

争用条件

有多个 SDK 客户端实例且读取在写入之前发生。

解决方案

  1. Azure Cosmos DB 的默认帐户一致性为会话一致性。 创建或更新项时,响应将返回一个会话令牌,该令牌可以在 SDK 实例之间传递,以确保读取请求在从具有该更改的副本中进行读取。
  2. 一致性级别更改为更高级别

读取容器或数据库资源的吞吐量

使用 PowerShell 或 Azure CLI 并收到“未找到”错误消息。

解决方案

可以在数据库级别和/或容器级别预配吞吐量。 如果收到“未找到”错误,请尝试读取父数据库资源或子容器资源的吞吐量。

分区键和 ID 组合无效

分区键和 ID 组合无效。

解决方案

修复导致错误组合的应用程序逻辑。

项 ID 中的字符无效

项已插入 Azure Cosmos DB,并且项 ID 中带有无效字符

解决方案

将 ID 更改为不包含特殊字符的其他值。 如果不能更改 ID,则可以对 ID 进行 Base64 编码以将特殊字符转义。 Base64 仍可以生成名称,其字符“/”无效,需要替换。

对于已经插入容器中的项,可以使用 RID 值来替换其 ID,而不使用基于名称的引用。

// Get a container reference that uses RID values.
ContainerProperties containerProperties = await this.Container.ReadContainerAsync();
string[] selfLinkSegments = containerProperties.SelfLink.Split('/');
string databaseRid = selfLinkSegments[1];
string containerRid = selfLinkSegments[3];
Container containerByRid = this.cosmosClient.GetContainer(databaseRid, containerRid);

// Invalid characters are listed here.
// /dotnet/api/microsoft.azure.documents.resource.id#remarks
FeedIterator<JObject> invalidItemsIterator = this.Container.GetItemQueryIterator<JObject>(
    @"select * from t where CONTAINS(t.id, ""/"") or CONTAINS(t.id, ""#"") or CONTAINS(t.id, ""?"") or CONTAINS(t.id, ""\\"") ");
while (invalidItemsIterator.HasMoreResults)
{
    foreach (JObject itemWithInvalidId in await invalidItemsIterator.ReadNextAsync())
    {
        // Choose a new ID that doesn't contain special characters.
        // If that isn't possible, then Base64 encode the ID to escape the special characters.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(itemWithInvalidId["id"].ToString());
        itemWithInvalidId["id"] = Convert.ToBase64String(plainTextBytes).Replace('/', '!');

        // Update the item with the new ID value by using the RID-based container reference.
        JObject item = await containerByRid.ReplaceItemAsync<JObject>(
            item: itemWithInvalidId,
            ID: itemWithInvalidId["_rid"].ToString(),
            partitionKey: new Cosmos.PartitionKey(itemWithInvalidId["status"].ToString()));

        // Validating the new ID can be read by using the original name-based container reference.
        await this.Container.ReadItemAsync<ToDoActivity>(
            item["id"].ToString(),
            new Cosmos.PartitionKey(item["status"].ToString())); ;
    }
}

生存时间清除

项已设置生存时间 (TTL) 属性。 因为 TTL 属性已过期,项已被清除。

解决方案

更改 TTL 属性以防止清除该项。

惰性索引编制

惰性索引编制未跟进。

解决方案

等待索引编制跟进或更改索引编制策略。

已删除父资源

项所在的数据库或容器已删除。

解决方案

  1. 从备份还原父资源或重新创建资源。
  2. 创建新资源来替换已删除的资源。

7.容器/集合名称区分大小写

容器/集合名称在 Azure Cosmos DB 中区分大小写。

解决方案

请确保在连接到 Azure Cosmos DB 时使用准确的名称。