从Aurora只读副本同步数据到DynamoDB时遇JSON循环结构转换错误
问题分析与解决方案
看起来你遇到了两个关键问题:一个是读取数据属性时的Cannot read property 'id' of undefined错误,另一个是JSON序列化时的循环结构错误。咱们一步步来解决:
1. 数据属性读取错误的原因与修复
你从Aurora拿到的结果是一个数组([ { "id": 2, "name": "Display", "result": "Pass" } ]),但代码里你把它包裹成了var data = {results};,也就是data是一个包含results数组的对象。这时候直接访问data.id肯定是undefined,因为id属性在data.results[0]里面。
修复方式:直接从results数组的第一个元素中提取属性:
// 原错误代码 var params = { Item:{ test_id:data.id, name:data.name, result:data.result }, TableName: 'demo_rds_dynamoDB' }; // 修复后 const record = results[0]; // 取数组里的第一条记录 var params = { Item:{ test_id: record.id, name: record.name, result: record.result }, TableName: 'demo_rds_dynamoDB' };
2. 循环结构JSON序列化错误的原因与修复
这个错误是因为你在connection.end的回调里,把client.put()的返回值直接传给了callback:
connection.end(function (err) { callback(err, client.put(params, function(error,data){ // ... }) ); });
client.put()返回的是AWS的请求对象,里面包含循环引用的结构(比如客户端实例的引用),当Lambda尝试把这个对象序列化为JSON返回时就会报错。而且这里的异步流程也有问题:client.put是异步操作,你应该在它的回调里才调用Lambda的callback,而不是把put的返回值传给callback。
修复后的异步流程应该是:
- 先执行DynamoDB的put操作
- 在put操作完成的回调里,关闭数据库连接
- 最后调用Lambda的callback返回结果或错误
完整修复后的代码
把所有问题修复后,完整代码如下:
var AWS = require("aws-sdk"); var mysql = require('mysql'); const client = new AWS.DynamoDB.DocumentClient({region : 'eu-west-1'}); var connection = mysql.createPool({ host : "**********", user : "****", password : "*****", database : "mydb", port : "3306" }); exports.handler = (event, context, callback) => { connection.query('select * from demo where id=2;', function (error, results, fields) { if (error) { connection.end(); return callback(error, null); } // 确保查询到了数据再继续,避免空数组报错 if (!results || results.length === 0) { connection.end(); return callback(new Error("No record found with id=2"), null); } const record = results[0]; var params = { Item:{ test_id: record.id, name: record.name, result: record.result }, TableName: 'demo_rds_dynamoDB' }; client.put(params, function(putError, putData){ connection.end(); if(putError){ return callback(putError, null); } callback(null, putData); }); }); };
额外优化建议
- 不要在Lambda里直接
throw error,应该用callback返回错误,否则会导致Lambda执行异常。 - 增加查询结果的空值判断,避免当没有查询到数据时访问
results[0]出现新的错误。 - 考虑使用
async/await来替代嵌套回调,让代码更易读(如果你的Node.js版本支持的话)。
内容的提问来源于stack exchange,提问作者ABCD
相关产品推荐
相关产品推荐

