

# DynamoDB 错误处理
<a name="Programming.Errors"></a>

 本节描述运行时系统错误，以及如何处理它们。它还描述特定于 Amazon DynamoDB 的错误消息和代码。有关适用于所有 AWS 服务的常见错误列表，请参阅[访问管理](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/CommonErrors.html)

**Topics**
+ [错误组成部分](#Programming.Errors.Components)
+ [事务性错误](#Programming.Errors.TransactionalErrors)
+ [错误消息和代码](#Programming.Errors.MessagesAndCodes)
+ [应用程序中的错误处理](#Programming.Errors.Handling)
+ [错误重试和指数回退](#Programming.Errors.RetryAndBackoff)
+ [批处理操作和错误处理](#Programming.Errors.BatchOperations)

## 错误组成部分
<a name="Programming.Errors.Components"></a>

程序发送请求后，DynamoDB 会尝试处理该请求。如果请求成功，DynamoDB 将返回一个 HTTP 成功状态代码 (`200 OK`)，以及所请求操作的结果。

如果请求失败，DynamoDB 会返回一个错误。每个错误包含三个部分：
+ HTTP 状态代码（如 `400`）。
+ 异常名称（如 `ResourceNotFoundException`）。
+ 错误消息（如 `Requested resource not found: Table: tablename not found`）。

AWS SDK 负责将错误传播到应用程序，以便您能执行适当操作。例如，在 Java 程序中，您可以编写 `try-catch` 逻辑以处理 `ResourceNotFoundException`。

如果您使用的不是 AWS SDK，将需要解析来自 DynamoDB 的低级响应内容。下面是一个此类响应的示例。

```
HTTP/1.1 400 Bad Request
x-amzn-RequestId: LDM6CJP8RMQ1FHKSC1RBVJFPNVV4KQNSO5AEMF66Q9ASUAAJG
Content-Type: application/x-amz-json-1.0
Content-Length: 240
Date: Thu, 15 Mar 2012 23:56:23 GMT

{"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",
"message":"Requested resource not found: Table: tablename not found"}
```

## 事务性错误
<a name="Programming.Errors.TransactionalErrors"></a>

有关事务性错误的信息，请参阅 [DynamoDB 中的事务冲突处理](transaction-apis.md#transaction-conflict-handling)

## 错误消息和代码
<a name="Programming.Errors.MessagesAndCodes"></a>

下面是 DynamoDB 返回的异常列表，按 HTTP 状态代码分组。如果*确定重试？*为*是*，则可以在此提交相同请求。如果*确定重试？*为*否*，则需要先解决客户端问题，然后再提交新请求。

### HTTP 状态代码 400
<a name="Programming.Errors.MessagesAndCodes.http400"></a>

HTTP `400` 状态代码表示与请求相关的问题，例如身份验证失败、缺少必需的参数或者超出预置表吞吐量。必须先解决应用程序中存在的问题，然后再重新提交请求。

**AccessDeniedException **  
消息：*访问被拒绝。*  
客户端未正确签名请求。如果使用 AWS SDK，系统将自动为您签署请求；否则，请参阅《AWS 一般参考》**中的[签名版本 4 签名流程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。  
确定重试？ 否

**ConditionalCheckFailedException**  
消息：*有条件请求失败。*  
指定条件的计算结果为 false。例如，您可能已尝试对项目执行有条件更新，但属性的实际值与条件预期值不匹配。  
确定重试？ 否

**IncompleteSignatureException**  
消息：*请求签名不符合 AWS 标准*  
请求签名未包含所有必需的部分。如果使用 AWS SDK，系统将自动为您签署请求；否则，请参阅《AWS 一般参考》**中的[签名版本 4 签名流程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。  
确定重试？ 否

**ItemCollectionSizeLimitExceededException**  
消息：*超过集合大小。*  
对于包含全局二级索引的表，具有相同分区键值的项目组超过 10 GB 最大大小限制。有关项目集的更多信息，请参见 [本地二级索引中的项目集合](LSI.md#LSI.ItemCollections)。  
确定重试？ 是

**LimitExceededException**  
消息：*指定订阅者的操作过多。*  
并发控制层面操作过多。处于 `CREATING`、`DELETING` 或 `UPDATING` 状态的表和索引的累计数量不能超过 500。  
确定重试？ 是

**MissingAuthenticationTokenException**  
消息：*请求必须包含有效(已注册)的 AWS 访问密钥 ID。*  
请求未包含所需的授权标头，或请求的格式不正确。请参阅 [DynamoDB 低级 API](Programming.LowLevelAPI.md)。  
确定重试？ 否

**ProvisionedThroughputExceededException**  
消息：*已超过表或一个或更多全局二级索引的最大允许预置吞吐量。要查看预置吞吐量与占用吞吐量的性能指标，请打开 [Amazon CloudWatch 控制台](https://console.aws.amazon.com/cloudwatch/home)。*  
错误包括 `ThrottlingReason` 字段的列表，这些字段按照格式 `ResourceType+OperationType+LimitType` 提供有关发生节流情况的具体背景信息（例如 `TableReadProvisionedThroughputExceeded`），错误中还包括受影响资源的 ARN。您可以利用这些信息来确定哪些资源受到限制（表或索引）、触发节流的操作类型（读取或写入）以及超过的特定限额（在本例中为预置容量）。有关诊断和解决节流问题的更多信息，请参阅[诊断节流](throttling-diagnosing-workflow.md)。  
示例：您的请求速率过高。DynamoDB 的 AWS SDK 自动重试收到此异常的请求。除非重试队列太长以致无法完成，否则请求最终都会成功。请使用[错误重试和指数回退](#Programming.Errors.RetryAndBackoff)降低请求频率，  
确定重试？ 是

**ReplicatedWriteConflictException**  
消息：*One or more items in this request are being modified by a request in another Region.*  
示例：已请求对多区域强一致性（MRSC）全局表中的项目执行写入操作，而该表当前正由另一个区域中的请求进行修改。  
确定重试？ 是

**RequestLimitExceeded**  
消息：*吞吐量超出您的账户的当前吞吐量限制。要请求提高限制，请联系 AWS Support：[https://aws.amazon.com/support](https://aws.amazon.com/support)*。  
错误包括 `ThrottlingReason` 字段的列表，这些字段按照格式 `ResourceType+OperationType+LimitType` 提供有关发生节流情况的具体背景信息（例如 `TableWriteAccountLimitExceeded` 或 `IndexReadAccountLimitExceeded`），错误中还包括受影响资源的 ARN。您可以利用这些信息确定哪些资源受到限制（表或索引）、触发节流的操作类型（读取或写入），以及您是否超过了账户级别的服务配额。有关诊断和解决节流问题的更多信息，请参阅[诊断节流](throttling-diagnosing-workflow.md)。  
示例：按需请求的速率超出允许的账户吞吐量，该表无法进一步扩展。  
确定重试？ 是

**ResourceInUseException**  
消息：*您尝试更改的资源正在使用中。*  
示例：您尝试重新创建现有表，或删除目前处于 `CREATING` 状态的表。  
确定重试？ 否

**ResourceNotFoundException **  
消息：*未找到请求的资源。*  
示例：您正在请求的表不存在，或过早进入 `CREATING` 状态。  
确定重试？ 否

**ThrottlingException**  
消息：*请求速率超出允许吞吐量。*  
此异常将作为 AmazonServiceException 响应返回，并带有 THROTTLING\$1EXCEPTION 状态代码。如果过快执行[控制层面](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.API.html#HowItWorks.API.ControlPlane) API 操作，则可能会返回此异常。  
对于使用按需模式的表，如果请求速率过高，则可能会针对任何[数据层面](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.API.html#HowItWorks.API.DataPlane) API 操作返回此异常。要了解有关按需扩展的更多信息，请参阅[初始吞吐量和扩展属性](on-demand-capacity-mode.md#on-demand-capacity-mode-initial)。  
错误包括 `ThrottlingReason` 字段的列表，这些字段按照格式 `ResourceType+OperationType+LimitType` 提供有关发生节流情况的具体背景信息（例如 `TableReadKeyRangeThroughputExceeded` 或 `IndexWriteMaxOnDemandThroughputExceeded`），错误中还包括受影响资源的 ARN。您可以利用此信息来确定哪些资源受到限制（表或索引）、触发节流的操作类型（读取或写入）以及超过的特定限额（分区限额还是按需最大吞吐量）。有关诊断和解决节流问题的更多信息，请参阅[诊断节流](throttling-diagnosing-workflow.md)。  
确定重试？ 是

**UnrecognizedClientException**  
消息：*访问密钥 ID 或安全令牌无效。*  
请求签名错误。最有可能的原因是 AWS 访问密钥 ID 或密钥无效。  
确定重试？ 是

**ValidationException**  
消息：根据遇到的特定错误而变化  
有多种原因可能导致此错误，例如缺少必需参数，值超出范围，或者数据类型不匹配。错误消息包含有关导致错误的请求特定部分的详细信息。  
确定重试？ 否

### HTTP 状态代码 5xx
<a name="Programming.Errors.MessagesAndCodes.http5xx"></a>

HTTP `5xx` 状态代码表示必须由 AWS 解决的问题。这可能是临时错误，在这种情况下，可以重试请求直到成功。否则，请转至 [AWS Service Health Dashboard](https://status.aws.amazon.com/)，查看是否存在与服务相关的任何操作问题。

有关更多信息，请参阅[如何解决 Amazon DynamoDB 中的 HTTP 5xx 错误？](https://aws.amazon.com/premiumsupport/knowledge-center/dynamodb-http-5xx-errors/)

**InternalServerError (HTTP 500)**  
DynamoDB 无法处理您的请求。  
确定重试？ 是  
处理项目时可能遇到内部服务器错误。这些是表的生命周期中的预期错误。可立即重试所有失败的请求。  
当您收到写入操作的状态代码 500 时，该操作可能已成功或失败。如果写入操作是 `TransactWriteItem` 请求，那么可以重试该操作。如果写入操作是单项写入请求，例如 `PutItem`、`UpdateItem` 或 `DeleteItem`，那么您应用程序应该在重试操作之前读取项目的状态，和/或使用 [DynamoDB 条件表达式 CLI 示例](Expressions.ConditionExpressions.md) 以确保项目在重试后保持正确的状态，无论之前的操作是成功还是失败。如果写入操作要求幂等性，请使用 [`TransactWriteItem`](transaction-apis.md#transaction-apis-txwriteitems)，它通过自动指定 `ClientRequestToken` 消除多次尝试执行同一操作的歧义，从而支持幂等性请求。

**ServiceUnavailable (HTTP 503)**  
DynamoDB 当前不可用。（这应是一种暂时状态。）  
确定重试？ 是

## 应用程序中的错误处理
<a name="Programming.Errors.Handling"></a>

为了让应用程序平稳运行，需要添加逻辑以抓取和响应错误。典型的方法包括使用 `try-catch` 块或 `if-then` 语句。

AWS SDK 执行自己的重试和检查错误。如果使用某个 AWS SDK 时遇到错误，错误代码和错误描述可帮助您纠正错误。

您还应该会在响应中看到 `Request ID`。如果需要使用 AWS 支持诊断问题，则 `Request ID` 会很有用。

## 错误重试和指数回退
<a name="Programming.Errors.RetryAndBackoff"></a>

网络上的大量组件（例如 DNS 服务器、交换机、负载均衡器等）都可能在某个指定请求生命周期中的任一环节出现问题。在联网环境中，处理这些错误响应的常规技术是在客户应用程序中实施重试。此方法提高应用程序的可靠性。

每个 AWS SDK 都会自动实现重试逻辑。可以修改重试参数以满足您的需求。例如，考虑一个需要 fail-fast 策略的 Java 应用程序，并且在出错时不允许重试。利用 适用于 Java 的 AWS SDK，您可以使用 `ClientConfiguration` 类并提供值为 `maxErrorRetry` 的 `0` 来禁用重试。有关更多信息，请参阅适用于您编程语言的 AWS SDK 文档。

如果您没有使用 AWS SDK，则应当对收到服务器错误 (5xx) 的原始请求执行重试。但是，客户端错误（4xx，不是 `ThrottlingException` 或 `ProvisionedThroughputExceededException`）表示您需要对请求本身进行修改，先修正了错误然后再重试。有关解决特定节流场景的详细建议，请参阅 [DynamoDB 节流故障排除](TroubleshootingThrottling.md)部分。

除了简单重试之外，每个 AWS SDK 还实施指数回退算法来实现更好的流程控制。指数回退的原理是对于连续错误响应，重试等待间隔越来越长。例如，第一次重试最多等待 50 毫秒，第二次重试最多等待 100 毫秒，第三次重试最多等待 200 毫秒，依此类推。但是，如果过段时间后，请求仍然失败，则出错的原因可能是因为请求大小超出预置吞吐量，而不是请求速率的问题。您可以设置最大重试次数，在大约一分钟的时候停止重试。如果请求失败，请检查您的预置吞吐量选项。

**注意**  
AWS SDK 实施自动重试逻辑和指数回退。

大多数指数回退算法会利用抖动（随机延迟）防止连续的冲突。由于在这些情况下不会尝试避免此类冲突，因此无需使用此随机数字。但是，如果使用并发客户端，抖动可帮助您更快地成功执行请求。有关更多信息，请参阅有关[指数回退和抖动](http://www.awsarchitectureblog.com/2015/03/backoff.html)的博文。

## 批处理操作和错误处理
<a name="Programming.Errors.BatchOperations"></a>

DynamoDB 低级 API 支持批量读取和写入操作。`BatchGetItem` 从一个或多个表中读取项目，`BatchWriteItem` 在一个或多个表中放置或删除项目。这些批量操作作为其他非批量 DynamoDB 操作的包装得以实现。换句话说，`BatchGetItem` 为批处理中的每个项目调用 `GetItem` 一次。同样，`BatchWriteItem` 根据需要为批处理中的每个项目调用 `DeleteItem` 或 `PutItem`。

批量操作可以容忍批处理中的个别请求失败。例如，假设一个 `BatchGetItem` 请求读取五个项目。即使某些底层 `GetItem` 请求失败，这也不会导致整个 `BatchGetItem` 操作失败。但是，如果所有五个读取操作都失败，则整个 `BatchGetItem` 失败。

批量操作会返回有关各失败请求的信息，以便您诊断问题并重试操作。对于 `BatchGetItem`，在响应的 `UnprocessedKeys` 值中会返回有问题的表和主键。对于 `BatchWriteItem`，在 `UnprocessedItems` 中返回类似信息。

造成读取失败或写入失败的最可能原因是*限制*。对于 `BatchGetItem`，原因是批量请求中的一个或多个表没有足够的预置读取容量来支持操作。对于 `BatchWriteItem`，原因是一个或多个表没有足够的预置写入容量。

如果 DynamoDB 返回了任何未处理的项目，应对这些项目重试批量操作。然而，*我们强烈建议您使用指数回退算法*。如果立即重试批量操作，底层读取或写入请求仍然会由于各表的限制而失败。如果使用指数回退延迟批量操作，批处理中的各请求成功的可能性更大。

**注意**  
一些 AWS SDK 提供更高级别的客户端，可以自动处理未处理的项目重试，因此您无需自行实施此重试逻辑。例如：  
**Java**：在执行批量操作时，适用于 Java 的 AWS SDK v2 中的 [DynamoDB 增强型客户端](DynamoDBEnhanced.md)和 v1 中的 [DynamoDBMapper](DynamoDBMapper.md) 都会自动重试未处理的项目。
**Python**：对于批量写入操作，boto3 表资源 `batch_writer` 隐式处理未处理的项目重试。有关更多信息，请参阅 [使用表资源 batch\$1writer](programming-with-python.md#programming-with-python-batch-writer)。
如果您使用的底层客户端或 SDK 不提供此行为，则必须按照上述方式自行实施重试逻辑。