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

Sequelize事务传入模型查询报错:relation 'users'不存在

问题解决:跨Sequelize实例传递事务导致"users表不存在"错误

问题场景

  • 定义了两个Sequelize实例:userSequelize(连接用户数据库)、transactionSequelize(连接事务数据库)
  • 在transferMoney函数中,从transactionSequelize创建事务并传入User.findOne查询时,抛出错误:ERROR: relation "users" does not exist at character 89
  • 移除查询中的transaction参数后,能正常获取用户信息

根因分析

事务对象与模型所属的Sequelize实例不匹配。User模型基于userSequelize实例定义(对应用户数据库),但你传入的事务是从transactionSequelize实例创建的——这个事务绑定的是事务数据库。当Sequelize执行查询时,会尝试在事务数据库中找users表,但该表只存在于用户数据库,因此报错。

解决方案

方案1:用用户库实例创建事务(适配需要事务控制的场景)

如果需要将用户表的查询/修改纳入事务范围,必须从userSequelize实例创建事务,而非transactionSequelize。如果同时需要操作事务数据库,可分别创建对应实例的事务:

修改控制器代码:

import { Request, Response } from 'express';
import User from '../models/user.js';
// 同时导入两个Sequelize实例
import { transactionSequelize, userSequelize } from '../database.js';
import Transaction from '../models/transaction.js';

const transferMoney = async (req: Request, res: Response) => {
    await Transaction.sync();
    // 分别创建对应数据库的事务
    const userTx = await userSequelize.transaction();
    const transTx = await transactionSequelize.transaction();
    
    try {
        const { transferFrom, transferTo, amount } = req.body;
        // 用用户库的事务查询用户
        const receiverExists = await User.findOne({
            where: { id: transferTo },
            transaction: userTx
        });

        if (!receiverExists) {
            // 回滚所有事务
            await userTx.rollback();
            await transTx.rollback();
            return res.status(404).send({ message: "Receiver not found" });
        }

        // 操作事务库时,使用事务库的事务
        await Transaction.create({
            fromId: transferFrom,
            toId: transferTo,
            amount
        }, { transaction: transTx });

        // 提交所有事务
        await userTx.commit();
        await transTx.commit();

        res.status(200).send({ message: "转账成功" });
    } catch (error) {
        // 异常时回滚所有事务
        await userTx.rollback();
        await transTx.rollback();
        res.status(500).send({ message: "Server Error" });
    }
}

export default { transferMoney };

方案2:移除事务参数(适配无需事务控制的查询场景)

如果只是校验用户是否存在(无数据修改操作),不需要将该查询纳入事务范围,直接去掉transaction参数即可:

const receiverExists = await User.findOne({
    where: { id: transferTo }
    // 移除transaction参数
});

关键提示

Sequelize的事务对象与创建它的实例强绑定,不能跨数据库实例使用。若需实现跨两个数据库的分布式事务,需要数据库本身支持(如PostgreSQL的分布式事务),并配置Sequelize对应的事务管理器,该场景复杂度较高,建议优先拆分单库事务逻辑。

内容的提问来源于stack exchange,提问作者Bhanu Prakash War

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:47:43