诊断和排查 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.
// https://learn.microsoft.com/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 时使用准确的名称。

后续步骤