Next.js读取RDS(MySQL)数据异常,求排查修复方案
问题:Next.js + mysql2/promise 从RDS读取数据时数据损坏
刚接触Next.js,使用mysql2/promise从RDS(MySQL)读取数据时遇到以下异常:
- 单条数据可正常展示,读取两条及以上数据时出现数据损坏;
- 单条数据读取成功的情况下,当
result_description列文本长度超过约150字符时,数据也会损坏。
已排查JSON格式干扰问题,调整该列varchar最大长度后问题仍存在,相关代码如下:
lib/db.js
import mysql from "mysql2/promise"; export async function LibDB(query, values) { const DbConnection = await mysql.createConnection({ host: process.env.DB_HOST, port: process.env.DB_PORT, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_DATABASE }); try { const [results] = await DbConnection.execute(query, values) DbConnection.end(); return results } catch (error) { throw Error(error.message); } }
pages/api/get_result.js
import{LibDB} from "../../lib/db" export default async function handler(req, res) { try { const query = "SELECT T.test_id, T.test_share, R.test_title, R.result_title, R.result_name, R.result_description, R.result_sub_description, R.result_image, R.result_image_kakao, R.result_image_facebook FROM tests_results R INNER JOIN logs L ON L.test_id = R.test_id AND L.result_type = R.result_type INNER JOIN tests T ON R.test_id = T.test_id WHERE L.log_id = ? AND L.test_id = ?"; const value = [req.query.logId, req.query.testId]; const data = await LibDB(query,value); // res.status(200).json({results: data}) res.status(200).send(data); } catch (error) { res.status(500).json({error: error.message}) res.status(500).send('error') } }
API调用代码
export async function getServerSideProps({params}){ const response = await axios.get(process.env.NEXT_PUBLIC_URL+"/api/get_result", {params: {logId: params.id, testId:1}}) const data =response.data return { props:{resultData: data} }; }
排查与修复方案
1. 修复响应序列化方式
当前API使用res.send(data)直接返回数据,该方法在处理复杂对象或长文本时,易因编码、序列化不完整导致数据损坏。必须改用res.json(),它会自动完成标准JSON序列化,适配多数据、长文本场景。
修改pages/api/get_result.js的响应代码:
// 替换原res.status(200).send(data); res.status(200).json({ results: data });
同时调整调用端getServerSideProps的取值逻辑:
const data = response.data.results;
2. 改用数据库连接池
每次请求创建新连接并手动关闭,可能因连接提前断开导致数据未完全读取。改用mysql2/promise的连接池,可自动管理连接生命周期,稳定性更高:
修改lib/db.js为连接池模式:
import mysql from "mysql2/promise"; // 创建连接池 const pool = mysql.createPool({ host: process.env.DB_HOST, port: process.env.DB_PORT, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_DATABASE, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); export async function LibDB(query, values) { try { const [results] = await pool.execute(query, values); return results; } catch (error) { throw new Error(error.message); } }
无需手动关闭连接,连接池会自动回收。
3. 检查字符编码与列类型
- 确认数据库、表、
result_description列的字符编码为utf8mb4,避免特殊字符、长文本转义出错; - 若该列存储大段文本,建议将类型从
varchar改为text或longtext,varchar的长度限制可能导致序列化截断。
4. 修正错误处理逻辑
当前API的catch块同时调用res.json()和res.send(),会导致重复发送响应引发异常,保留一种即可:
catch (error) { res.status(500).json({ error: error.message }); }
内容的提问来源于stack exchange,提问作者user19790501
相关产品推荐
相关产品推荐

