用 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 itemConditionCheck——对一个事务并不修改的项目断言一个条件,条件不成立就否决整个事务。--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 可以针对真实的表编辑项目,并把它生成的表达式展示给你看。
相关示例
- Node.js 中的 DynamoDB TransactWriteItems——用 AWS SDK v3 做同样的事务。
- Python 中的 DynamoDB TransactWriteItems——用 boto3 做同样的事务。
- 用 AWS CLI 执行 DynamoDB BatchWriteItem——不需要原子性时的批量写入。
- DynamoDB 事务——隔离性、幂等性,以及事务什么时候值得用。
- DynamoDB TransactionCanceledException——每一个取消原因码,逐个解码。
- "Too many actions in a TransactWriteItems call"——100 个动作与 4 MB 的事务限制。
- "Transaction request cannot include multiple operations on one item"——每个事务里每个项目只能有一个动作。
参考资料
- TransactWriteItems — Amazon DynamoDB API Reference
- transact-write-items — AWS CLI Command Reference
- Amazon DynamoDB transactions: how it works — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
最后核实于 2026-07-28,依据上方链接的 AWS 官方文档。