Node.js(AWS SDK v3)中的 DynamoDB TransactWriteItems
TransactWriteItems 把多达 100 次写入组成一次全有或全无的操作——要么每个动作都提交,要么一个都不提交。在 AWS SDK v3 中,你发送一个 TransactWriteItemsCommand,其 TransactItems 数组混合了 Put、Update、Delete 和 ConditionCheck 动作,每个都可带一个可选条件。
Code
import {DynamoDBClient, TransactWriteItemsCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
// Move one award between two songs — atomically. If the first song has no
// award to give, NEITHER update happens.
const command = new TransactWriteItemsCommand({
TransactItems: [
{
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'}}
}
}
]
});
try {
await client.send(command);
console.log('Transaction committed');
} catch (err) {
if (err.name === 'TransactionCanceledException') {
// One reason per action, in TransactItems order. 'None' means that action
// was fine — some OTHER action sank the transaction.
const codes = (err.CancellationReasons ?? []).map((r) => r.Code);
console.log('Transaction canceled:', codes); // e.g. ['ConditionalCheckFailed', 'None']
} else {
throw err;
}
}说明
TransactItems— 多达 100 个Put/Update/Delete/ConditionCheck动作,合计 4 MB。动作可以跨表(同一账户 + 区域),但任意两个动作都不可针对同一个项目——仅此一条就会取消事务。ConditionCheck— 对事务不修改的某个项目断言一个条件(例如"该账户仍然存在"),若失败则否决整个事务。TransactionCanceledException— 唯一需要处理的错误。err.CancellationReasons按顺序为每个动作列出一个{Code, Message}——代码包括ConditionalCheckFailed、TransactionConflict(另一个事务在中途触及了某个项目——可用退避安全重试)、ProvisionedThroughputExceeded和ValidationError;None标记无辜的动作。在某个动作上设置ReturnValuesOnConditionCheckFailure: 'ALL_OLD'可在其原因中获得失败项目的属性。ClientRequestToken— 传入一个可让调用在 10 分钟内保持幂等;网络超时后的 SDK 重试便不会把写入应用两次。- 成本 — 事务写入每个项目消耗两次底层写入(准备 + 提交),因此计费大约是普通写入 WCU 的 2 倍。当一次单项条件写入已能为单个项目提供原子性时,不要动用事务。
可视化操作
每个动作内部的条件和更新表达式才是繁琐之处——DynamoDB Expression Builder 会连同名称/值映射一起组装它们,并复制可运行代码。
想在 GUI 中编辑项目并审阅生成的表达式——请下载 DynoTable。
相关示例
- Python 中的 DynamoDB TransactWriteItems — 用 boto3 完成同样的事务。
- 使用 AWS CLI 的 DynamoDB TransactWriteItems — 在 shell 中完成同样的事务。
- Node.js 中的 DynamoDB 条件写入 — 无需 2 倍成本的单项原子性。
- DynamoDB 事务 — 隔离性、幂等性,以及事务何时值得使用。
- DynamoDB TransactionCanceledException — 每个取消原因代码的解读。
- "Too many actions in a TransactWriteItems call" — 100 个动作和 4 MB 的事务限制。
- "Transaction request cannot include multiple operations on one item" — 每个事务中每个项目只能有一个动作。
References
- TransactWriteItems — Amazon DynamoDB API Reference
- Amazon DynamoDB transactions: how it works — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.