You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AWS Lambda批量写入DynamoDB时数据丢失,无报错无未处理项

问题分析与可能原因

针对你遇到的Lambda批量写入DynamoDB后数据量不符的问题,结合代码和日志信息,以下是几个核心排查方向:


1. 数据统计时未处理DynamoDB查询分页限制

DynamoDB的Scan/Query操作单次返回结果上限为1MB数据或1000条记录(取较小值)。如果统计数据时只执行了一次查询,未通过LastEvaluatedKey进行分页遍历,你看到的14000条很可能只是单次查询的部分结果,实际20000条数据已全部写入。

验证方式:执行查询时循环处理LastEvaluatedKey,直到结果中无该字段,再汇总所有分页的记录数。


2. 代码中表名引用不一致

你的代码存在两处表名引用:

  • 批量写入逻辑使用硬编码的"myTable"作为表名
  • 最后一批数据的写入判断使用CardManager.instance().getTableName()获取表名

如果这两个表名不统一,最后一批未凑满24条的数据会被直接忽略,无法写入目标表。虽然该问题只会导致少量数据丢失,但仍需确认表名是否完全一致。

修复建议:统一使用动态获取的表名,避免硬编码:

async function writeOnDynamoDB(items: any, ruleId: string) {
    const dynamoDB = new AWS.DynamoDB.DocumentClient();
    const tableName = CardManager.instance().getTableName(); // 统一获取表名
    const batchWriteParams: AWS.DynamoDB.DocumentClient.BatchWriteItemInput = {
        RequestItems: {
            [tableName]: [],
        },
    };
    console.log('Start inserting rows')
    for (let i = 0; i < items.length; i++) {
        let item = items[i];
        item.id = ruleId

        const putRequest: AWS.DynamoDB.DocumentClient.WriteRequest = {
            PutRequest: {
                Item: item,
            },
        };
        
        batchWriteParams.RequestItems[tableName].push(putRequest);
        
        if (i > 0 && i % 24 === 0) {
            console.log("Insert chunck", i,)
            const result = await dynamoDB.batchWrite(batchWriteParams).promise();
            console.log('Result',result)
            batchWriteParams.RequestItems[tableName] = [];
        }
    }
    
    if (batchWriteParams.RequestItems[tableName].length > 0) {
        await dynamoDB.batchWrite(batchWriteParams).promise();
    }
}

3. 同一分区键写入的隐性流量控制

尽管表使用按需模式,但DynamoDB对单个分区键的写入有初始吞吐量限制(默认每秒1000次写入)。短时间内向同一分区键写入20000条数据,可能触发流量控制,部分写入操作未返回UnprocessedItems但实际未成功落地。

修复建议:添加UnprocessedItems重试逻辑(带指数退避),确保所有请求被处理:

async function batchWriteWithRetry(params: AWS.DynamoDB.DocumentClient.BatchWriteItemInput) {
    let result = await dynamoDB.batchWrite(params).promise();
    // 循环重试未处理的请求
    while (Object.keys(result.UnprocessedItems).length > 0) {
        await new Promise(resolve => setTimeout(resolve, 200)); // 指数退避可优化
        result = await dynamoDB.batchWrite({ RequestItems: result.UnprocessedItems }).promise();
    }
}

// 替换原batchWrite调用
await batchWriteWithRetry(batchWriteParams);

4. 输入数据存在隐性重复(覆盖写入)

即使你确认partitionKey+sortkey组合唯一,仍可能存在代码逻辑导致键组合重复:

  • item.id = ruleId修改了分区键或排序键,破坏了原本的唯一性
  • items数组中存在引用同一对象的元素,修改id后多个item的键组合一致,后续PutRequest覆盖了之前的写入

验证方式:写入前打印所有item的partitionKey和sortkey值,确认组合唯一;或写入后查询所有数据的键组合,检查是否存在重复。


内容的提问来源于stack exchange,提问作者Mikfaina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:07:04