Sequelize配置读写分离连接池时读操作始终命中写库问题
问题根因
核心原因是你用sequelize.query写原生SQL时没显式指定查询类型,Sequelize默认把所有未标记类型的原生查询全路由到写库。
Sequelize的读写分离路由逻辑不会主动解析你传入的SQL内容判断是读还是写,完全依赖调用时传入的options.type参数做路由决策:
- 只有
options.type明确设置为Sequelize.QueryTypes.SELECT,同时没有绑定事务、没有强制指定useMaster: true的查询,才会被路由到读节点连接池 - 其余所有查询,包括默认的RAW类型、增删改类写操作、事务内的所有查询,都会被路由到写节点池
你提到互换读写库配置后读操作“正常访问读节点”属于测试误判:互换配置后你大概率没有执行写入操作再校验读结果,仅靠存量历史数据判断路由去向,实际上未标记类型的原生查询不管怎么调整读写节点配置,始终会走写节点。
修复方案
1. 原生查询显式标记查询类型
给SELECT类查询手动添加type参数即可,写操作无需额外配置,修正后的测试代码参考:
const { Sequelize, QueryTypes } = require('sequelize'); app.get('/', async function(req, res){ // 标记为SELECT类型,自动路由到读库 const readRes = await sequelize.query("select * from users", { type: QueryTypes.SELECT }); // 写操作默认路由到写库,无需额外配置 const writeRes = await sequelize.query("insert into users(name,status) values('user11',1)"); // 标记为SELECT类型,自动路由到读库 const readRes1 = await sequelize.query("select * from users", { type: QueryTypes.SELECT }); res.send({ readRes, readRes1 }); });
2. 其他注意事项
- 日常使用Sequelize内置的模型方法(比如
findAll/findOne等读方法、create/update等写方法)时无需手动标记类型,框架会自动识别查询类型,完成读写节点路由 - 刚执行完写操作需要立刻读取最新数据的场景不要强行走读库,主从复制存在延迟,可能查不到刚写入的数据,这类场景可以给查询加
useMaster: true强制走写库 - 你贴的初始化配置本身没有语法问题,port这类公共参数放在顶层会自动被所有读写节点继承,不需要在每个节点下重复配置
内容的提问来源于stack exchange,提问作者RohitS
相关产品推荐
相关产品推荐

