使用npm mssql包查询SQL Server出现缓存问题求助
问题
使用npm的mssql包从SQL Server获取数据,尽管数据库中的数据已更新,但每次通过Postman发起请求时,都得到相同的结果集。
连接配置及代码如下:
const sql = require('mssql'); const config = { user: 'XXXX', password: 'XXXX', server: 'XXXX', database: 'XXXX', pool: { max: 50, min: 0, idleTimeoutMillis: 10 }, options: { trustServerCertificate: true } } const getConnection = async () => { try { const conn = await sql.connect(config); return {pool: conn, err: false, errorMSG: null}; } catch (err) { return {conn: null, err: true, errorMSG: err} } };
数据库操作函数:
const conn = await getConnection(); if (conn.err == false) { try { let result = await conn.pool.request() .input('registryNumber', sql.NVarChar(50), registryNumber) .input('password', sql.NVarChar(50), password) .query('SELECT role FROM [OperatorLogin].[dbo].[TBL_users]' + 'WHERE [TBL_users].[registryNumber] = @registryNumber AND [TBL_users].[password] = @password AND [TBL_users].[isActive] = 1 ') if (result.rowsAffected[0] >= 1) { return { Execution: true, ExecutionCode: 1, ExecutionMessage: "Record is available", ExecutionData: result.recordset } } else { return { Execution: true, ExecutionCode: 2, ExecutionMessage: "No records", ExecutionData: "" } } } catch (err) { return { Execution: false, ExecutionCode: -1, ExecutionMessage: "DB pool request error : " + err, ExecutionData: "" } } } else { return { Execution: false, ExecutionCode: -1, ExecutionMessage: " DB error : " + conn.errorMSG, ExecutionData: "" } }
服务器环境:Windows服务器,使用pm2和反向代理。请问可能是什么问题?忽略了哪些要点?
排查方向与解决方案
连接池与事务隔离级别问题
mssql的sql.connect()是全局单例模式,多次调用会复用同一个连接池。如果连接池中的连接处于REPEATABLE READ等隔离级别,会导致同一连接重复读取同一数据快照。
解决:- 查询时显式设置隔离级别为
READ COMMITTED:await conn.pool.request() .query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED') .input('registryNumber', sql.NVarChar(50), registryNumber) .input('password', sql.NVarChar(50), password) .query('SELECT role FROM [OperatorLogin].[dbo].[TBL_users] WHERE ...') - 开启数据库的
READ_COMMITTED_SNAPSHOT选项:ALTER DATABASE [OperatorLogin] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
- 查询时显式设置隔离级别为
反向代理缓存
反向代理(如Nginx、IIS)可能对API请求结果开启了静态缓存,导致返回旧数据。
解决:- 对动态API接口添加禁用缓存的响应头:
Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 - 直接访问应用端口(绕过反向代理)测试,确认是否为代理缓存问题。
- 对动态API接口添加禁用缓存的响应头:
PM2进程内存缓存
如果代码中存在全局变量缓存查询结果(如将查询结果存在模块级变量中),PM2启动的进程会一直复用旧数据,直到进程重启。
解决:- 检查代码逻辑,确保每次请求都重新执行数据库查询,不依赖全局缓存。
- 执行
pm2 restart <应用名称>重启进程,验证是否恢复正常。
数据库更新未提交
确认数据库中的数据更新操作是否已提交事务。如果在SSMS等工具中修改数据后未执行COMMIT,其他连接将无法看到更新。
解决:修改数据后执行COMMIT语句,或开启工具的自动提交功能。连接池配置不合理
配置中idleTimeoutMillis: 10过小,会导致连接频繁销毁重建,也可能因连接复用逻辑异常读取旧数据;且每次请求都调用sql.connect()会重复初始化连接池。
解决:- 将
idleTimeoutMillis调整为合理值(如30000,即30秒)。 - 应用启动时仅初始化一次连接池,后续操作直接复用:
// 应用启动阶段初始化 let pool; const initPool = async () => { pool = await sql.connect(config); }; initPool(); // 数据库操作时直接使用pool const result = await pool.request() .input('registryNumber', sql.NVarChar(50), registryNumber) .input('password', sql.NVarChar(50), password) .query('SELECT role FROM [OperatorLogin].[dbo].[TBL_users] WHERE ...')
- 将
内容的提问来源于stack exchange,提问作者Mvlepod
相关产品推荐
相关产品推荐

