用 AWS CLI 执行 DynamoDB TransactWriteItems

整个事务作为一个 --transact-items JSON 数组交给 aws dynamodb transact-write-items,所以 CLI 的边角才是有意思的部分:引号在哪里崩、退出码意味着什么,以及默认的错误输出会丢掉你调试取消所需要的那个字段。事务能给你买到什么在每个 SDK 里都是一样的。

代码

aws dynamodb transact-write-items \
  --transact-items '[
    {
      "Update": {
        "TableName": "Music",
        "Key": {"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
        "UpdateExpression": "SET #upd0 = #upd0 - :one",
        "ConditionExpression": "#upd0 >= :one",
        "ExpressionAttributeNames": {"#upd0": "Awards"},
        "ExpressionAttributeValues": {":one": {"N": "1"}}
      }
    },
    {
      "Update": {
        "TableName": "Music",
        "Key": {"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "A Mis Abuelos"}},
        "UpdateExpression": "SET #upd0 = if_not_exists(#upd0, :zero) + :one",
        "ExpressionAttributeNames": {"#upd0": "Awards"},
        "ExpressionAttributeValues": {":one": {"N": "1"}, ":zero": {"N": "0"}}
      }
    }
  ]'

一个提交成功的事务什么都不打印,退出码为 0。没有响应体可以检查,所以在脚本里退出码就是结果。

说明

  • --transact-items——最多 100 个 Put / Update / Delete / ConditionCheck 动作,合计 4 MB,值为 DynamoDB JSON。这些动作可以跨同一账户与区域内的多张表,且其中任意两个都不能针对同一个项目。

  • 三种退出码,三种不同的失败0 表示已提交。252 表示 CLI 自己的参数校验拒绝了这个请求,什么都没发出去。254 表示 DynamoDB 应答了并且说不行。这个区分值得拿来分支:252 是你 JSON 里的 bug,254 可能是你本来就预期会失败的条件。

  • 默认的错误格式会丢掉每个动作的原因。aws-cli v2 打印摘要,然后告诉你它扣下了细节:

    aws: [ERROR]: An error occurred (TransactionCanceledException) when calling the TransactWriteItems operation: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]
    
    Additional error details:
    CancellationReasons: <complex value>
    Use "--cli-error-format json" or another error format to see the full details.

    --cli-error-format json 重跑同一条命令,结构就完整地到手了,每个动作一条,顺序与 --transact-items 一致:

    {
        "Message": "Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]",
        "Code": "TransactionCanceledException",
        "CancellationReasons": [
            {
                "Code": "ConditionalCheckFailed",
                "Message": "The conditional request failed"
            },
            {
                "Code": "None"
            }
        ]
    }

    这里是第一个更新的 Awards >= 1 条件没过;None 把第二个动作标记为无辜,而且注意它压根没有 Message 字段。其余每一个码都在 TransactionCanceledException 页面上解码

  • 对同一个项目下两次手不算取消。它在任何动作被尝试之前就没通过校验,所以也就没有原因可打印:

    aws: [ERROR]: An error occurred (ValidationException) when calling the TransactWriteItems operation: Transaction request cannot include multiple operations on one item
  • ConditionCheck——对一个事务并不修改的项目断言一个条件,条件不成立就否决整个事务。

  • --client-request-token——固定的 token 让重跑在 10 分钟内是幂等的。用同一个 token 但改动了任何参数,DynamoDB 会返回 IdempotentParameterMismatch,而不是默默地应用新的载荷。

  • 把这个数组放进文件里--transact-items file://transaction.json 彻底绕开 shell 引号转义,而且这个文件可以做 diff。

那个 2× 在 shell 里就能量出来

把同一个单项目更新跑两次,一次放在事务里,一次不放,两次都带 --return-consumed-capacity TOTAL。DynamoDB Local 为事务写入报告 2.0 个容量单元,为普通写入报告 1.0:准备和提交各计一次费。

这就是「不要默认伸手去拿事务」的全部论据。要在单个项目上获得原子性,你已经有一个更便宜的工具——条件写入,它只计一次费。要给一个每月做上百万次这种操作的工作负载定价,DynamoDB 定价计算器可以直接接受翻倍后的写入次数。如果你想彻底不再在 shell 里拼 DynamoDB JSON,DynoTable 可以针对真实的表编辑项目,并把它生成的表达式展示给你看。

相关示例

参考资料

最后核实于 2026-07-28,依据上方链接的 AWS 官方文档。

无需控制台即可使用 DynamoDB

一款快速的 DynamoDB 桌面客户端,可运行 DynamoDB 无法执行的真正 SQL——JOINs、GROUP BY、聚合——并支持可视化编辑和运行在你自己的 Bedrock 密钥上的 AI agent。

30 天免费试用,无需信用卡 — 之后为无时间限制的免费版。