诊断和排查 Azure Cosmos DB 的“未找到”异常Diagnose and troubleshoot Azure Cosmos DB not found exceptions

适用于: SQL API

HTTP 状态代码 404 表示资源不再存在。The HTTP status code 404 represents that the resource no longer exists.

预期行为Expected behavior

应用程序预期接收代码 404 并正确进行处理的有效方案有许多。There are many valid scenarios where an application expects a code 404 and correctly handles the scenario.

对应该存在或确实存在的项返回了“未找到”异常A not found exception was returned for an item that should exist or does exist

以下是在该项应该或确实存在的情况下返回状态代码 404 的可能原因。Here are the possible reasons for a status code 404 to be returned if the item should exist or does exist.

读取会话不可用于输入会话令牌The read session is not available for the input session token

解决方案:Solution:

  1. 将当前 SDK 更新到已发布的最新版本。Update your current SDK to the latest version available. 此特定错误的最常见原因问题已在最新版 SDK 中得到解决。The most common causes for this particular error have been fixed in the newest SDK versions.

争用条件Race condition

有多个 SDK 客户端实例且读取在写入之前发生。There are multiple SDK client instances and the read happened before the write.

解决方案:Solution:

  1. Azure Cosmos DB 的默认帐户一致性为会话一致性。The default account consistency for Azure Cosmos DB is session consistency. 创建或更新项时,响应将返回一个会话令牌,该令牌可以在 SDK 实例之间传递,以确保读取请求在从具有该更改的副本中进行读取。When an item is created or updated, the response returns a session token that can be passed between SDK instances to guarantee that the read request is reading from a replica with that change.
  2. 一致性级别更改为更高级别Change the consistency level to a stronger level.

分区键和 ID 组合无效Invalid partition key and ID combination

分区键和 ID 组合无效。The partition key and ID combination aren't valid.

解决方案:Solution:

修复导致错误组合的应用程序逻辑。Fix the application logic that's causing the incorrect combination.

项 ID 中的字符无效Invalid character in an item ID

项被插入 Azure Cosmos DB,并且项 ID 中带有无效字符An item is inserted into Azure Cosmos DB with an invalid character in the item ID.

解决方案:Solution:

将 ID 更改为不包含特殊字符的其他值。Change the ID to a different value that doesn't contain the special characters. 如果不能更改 ID,则可以对 ID 进行 Base64 编码以将特殊字符转义。If changing the ID isn't an option, you can Base64 encode the ID to escape the special characters. Base64 仍然会生成一个包含无效字符“/”的名称,该字符需要替换。Base64 can still produce a name with a invalid character '/' which needs to be replaced.

对于已经插入容器中的项,可以使用 RID 值来替换其 ID,而不使用基于名称的引用。Items already inserted in the container for the ID can be replaced by using RID values instead of name-based references.

// 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://docs.azure.cn/dotnet/api/microsoft.azure.documents.resource.id?view=azure-dotnet&preserve-view=true#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())); ;
    }
}

生存时间清除Time to Live purge

项已设置生存时间 (TTL) 属性。The item had the Time to Live (TTL) property set. 由于 TTL 属性已过期,项被清除。The item was purged because the TTL property expired.

解决方案:Solution:

更改 TTL 属性以防止清除该项。Change the TTL property to prevent the item from being purged.

惰性索引编制Lazy indexing

惰性索引编制未跟进。The lazy indexing hasn't caught up.

解决方案:Solution:

等待索引编制跟进或更改索引编制策略。Wait for the indexing to catch up or change the indexing policy.

已删除父资源Parent resource deleted

项所在的数据库或容器已删除。The database or container that the item exists in was deleted.

解决方案:Solution:

  1. 还原父资源或重新创建资源。Restore the parent resource, or re-create the resources.
  2. 创建新资源来替换已删除的资源。Create a new resource to replace the deleted resource.

7.容器/集合名称区分大小写7. Container/Collection names are case-sensitive

容器/集合名称在 Cosmos DB 中区分大小写。Container/Collection names are case-sensitive in Cosmos DB.

解决方案:Solution:

请确保在连接到 Cosmos DB 时使用确切的名称。Make sure to use the exact name while connecting to Cosmos DB.

后续步骤Next steps