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

Node.js Sequelize MySQL异步事务报错:指定DEFINER用户不存在

问题:Sequelize事务中出现Definer不存在错误,普通请求正常

在Node.js应用中使用Sequelize异步事务处理POST请求时,抛出错误:

FailedSequelizeDatabaseError The user specified as a definer ldgybxav_ph1_admin@49.37.47.142 does not exist

但使用相同数据库凭据执行普通GET/POST请求(非事务场景)时,数据库交互完全正常。相关代码如下:

router.post('/medicineretailsalereturn', async (req, res) => {
    console.log("Medicine Retail Return Calls......");
    console.log(req.body);
    var sequelize = common.setPharmaDBConn4SQL(req.headers['pharma_id']);
    const t = await sequelize.transaction();
    try {
        req.body.bill.med_sale_date = new Date();
        req.body.bill.med_bill_number = billgenerator(3);
        req.body.bill.record_created_date = new Date();
        var medicineSellBill = await MedicineRetailSaleBill.create(req.body.bill, { transaction: t });
        for (var medCount = 0; medCount < req.body.items.length; medCount++) {
            var sellReturnJSON = req.body.items[medCount];
            sellReturnJSON.med_bill_id = medicineSellBill.med_sale_bill_id;
            sellReturnJSON.record_created_date = new Date();
            if(sellReturnJSON.med_bill_number != null) sellReturnJSON.med_sell_bill_number = sellReturnJSON.med_bill_number;
            
            if(sellReturnJSON.med_bill_number == null) {
                sellReturnJSON.med_bill_number = medicineSellBill.med_bill_number;
                console.log("Sell Deatils");
                console.log(sellReturnJSON);
                await MedicineRetailSaleDetails.create(sellReturnJSON, { transaction: t });
            } else {
                sellReturnJSON.med_bill_number = medicineSellBill.med_bill_number;
                console.log("Sell Retun Deatils");
                console.log(sellReturnJSON);
                await MedicineRetailReturnDetails.create(sellReturnJSON, { transaction: t });
            }
        }
        await t.commit();
        res.status(200).send("Medicine Reatils Sell/Return Bill Number :" + medicineSellBill.med_bill_number);
    } catch (error) {
        console.log("Error :" + error)
        await t.rollback();
        res.status(200).send("Medicine Reatils Sell/Return Failed" + error);
    }
});

可能的原因

这个错误核心和MySQL的视图、存储过程、触发器绑定的DEFINER(定义者)有关:这些数据库对象创建时会指定一个DEFINER用户,当事务中执行涉及这些对象的操作时,MySQL会严格检查该DEFINER是否存在;而普通请求可能没触发这些对象的执行逻辑,所以不会暴露问题。

另外,事务模式下Sequelize可能触发了模型关联的特殊操作,或者common.setPharmaDBConn4SQL创建的事务连接存在权限/用户不一致的情况。

解决方案

1. 定位并修复问题数据库对象

登录MySQL服务器,执行以下SQL找出所有使用该不存在DEFINER的对象:

-- 查找关联的视图
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE DEFINER = 'ldgybxav_ph1_admin@49.37.47.142';

-- 查找关联的存储过程/函数
SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE DEFINER = 'ldgybxav_ph1_admin@49.37.47.142';

-- 查找关联的触发器
SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS WHERE DEFINER = 'ldgybxav_ph1_admin@49.37.47.142';

找到对象后,将它们的DEFINER替换为当前应用使用的有效数据库用户,同时建议设置SQL SECURITY INVOKER(使用执行该对象的用户权限,而非DEFINER权限):

-- 修改视图DEFINER
ALTER VIEW `your_view_name` DEFINER = 'valid_user@your_host' SQL SECURITY INVOKER;

-- 修改存储过程DEFINER
ALTER PROCEDURE `your_procedure_name` DEFINER = 'valid_user@your_host' SQL SECURITY INVOKER;

-- 修改触发器(需先删除再重建)
DROP TRIGGER `your_trigger_name`;
DELIMITER //
CREATE TRIGGER `your_trigger_name` AFTER INSERT ON `target_table`
FOR EACH ROW
BEGIN
    -- 原触发器逻辑
END //
DELIMITER ;

2. 检查模型与事务连接

  • 确认MedicineRetailSaleDetails、MedicineRetailReturnDetails模型是否关联了带有问题DEFINER的视图/触发器,必要时调整模型定义避免直接操作这些对象。
  • 检查common.setPharmaDBConn4SQL函数,确保事务使用的数据库连接和普通请求使用的是同一套凭据,避免出现连接切换导致的用户不一致。

内容的提问来源于stack exchange,提问作者Krish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:52:07