向DynamoDB插入记录时的事务回滚处理方案咨询
解决方案
因为DynamoDB的transactWrite仅支持单请求内100条操作的原子性,跨请求的事务没有原生的全有全无支持,你可以通过以下几种方式实现500条数据的原子插入:
1. 预校验+补偿回滚(最可靠的同步方案)
这是最直接的落地方式,核心思路是先确保所有数据可写入,再分批提交,失败时回滚已提交的批次:
- 预校验所有数据:
- 用
BatchGetItem批量检查所有500条数据的主键是否已存在(如果是插入操作),或验证属性是否符合表Schema、依赖关系是否满足。 - 写入每个批次时,给每条操作加上条件表达式(比如插入时用
attribute_not_exists(partition_key)),避免并发写入导致的冲突。
- 用
- 记录回滚日志:
- 创建一张专门的回滚日志表,结构可设为:
batch_id(批次唯一标识)、item_keys(该批次所有数据的主键集合)、operation_type(如PUT/DELETE)、status(COMMITTED/ROLLED_BACK)。 - 每成功提交一个
transactWrite批次后,立即将该批次的写入记录原子性写入回滚日志表(可单独用transactWrite操作日志表,确保日志写入成功后再推进下一批)。
- 创建一张专门的回滚日志表,结构可设为:
- 失败触发回滚:
- 若某个批次提交失败,立即遍历回滚日志表中所有
status=COMMITTED的批次,对每个批次的每条数据执行反向操作:插入的执行DeleteItem,更新的恢复预存的原数据(需提前把原数据存入日志)。 - 回滚操作同样用
transactWrite批量执行,确保回滚的原子性,完成后更新日志的status为ROLLED_BACK。
- 若某个批次提交失败,立即遍历回滚日志表中所有
2. 全局状态锁+事后清理(适合无并发场景)
如果你的写入操作没有并发竞争,可用全局标记控制最终有效性:
- 写入前置锁:先向DynamoDB写入一条锁记录,比如主键为
global_lock,属性status设为PENDING,用transactWrite确保锁是原子创建的(条件attribute_not_exists(global_lock))。 - 分批写入数据:每批次写入后,记录已写入的主键集合。
- 最终提交/清理:
- 所有批次成功写入后,将锁记录的
status改为COMMITTED。 - 若中途失败,直接删除所有已写入的数据(用
BatchWriteItem或分批transactWrite删除),再删除锁记录。
- 所有批次成功写入后,将锁记录的
- 注意:此方案在有并发写入时会出现数据冲突,仅适合单进程、无并发的场景。
3. 利用DynamoDB Streams做异步补偿(适合非强实时场景)
如果业务允许短暂的不一致,可通过流监听写入失败事件,异步执行回滚:
- 开启目标表的DynamoDB Streams,捕获所有写入操作。
- 编写Lambda函数监听流事件,记录所有成功写入的主键。
- 主流程的批次写入失败时,触发Lambda函数遍历已记录的主键,执行删除操作。
- 此方案的缺点是会有短暂的数据存在时间,不适合要求严格即时一致性的业务。
关键注意事项
- 回滚操作本身要处理失败,比如设置3-5次重试机制,若重试失败则标记为待人工处理,避免数据不一致。
- 预校验和写入之间的时间窗口可能存在并发写入,必须在写入时加条件表达式,确保数据的唯一性或合法性。
- 所有日志写入和回滚操作都要保证幂等性,避免重复执行导致的错误。
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

