如果你使用了MySQL:MyISAM不支持事务处理,请换成InnoDB!!!
在使用Node.js进行服务端开发中我们经常使用Sequelize作为ORM框架,我们对多个数据表进行处理时通常会使用事务处理。在Sequelize事务文档中给了很多方式,主要分为托管和非托管,很多时候我们在回滚时常常发生失败,明明自己以及提交回滚了,但是仍然有数据表被改动了。
下面是我项目中的一个Demo,在tag表删除数据时,对article表中的tag进行置换,如果置换失败则事务回滚取消删除。在置换时我对id进行了 11,使得触发回滚进行测试。
代码语言:javascript复制import Router from "@koa/router";
import DB from "@/db";
import sequelize from "@/db/config";
import { Op } from "sequelize";
let router = new Router();
router.delete("/tag/:id", async ctx => {
let { id } = ctx.params;
const t = await sequelize.transaction();
let deleteTagCount = await DB.Tag.destroy({
where: {
id: id,
},
transaction: t,
});
// todo 解决事务处理问题
/** 需要删除的个数*/
let { count: tagCount } = await DB.Article.findAndCountAll({
where: { tag: { [Op.substring]: id } },
});
//将文章表中的 ,id, ,id id, id 四种方法全部置换 // 11使得置换失败,触发回滚
let replaceTagIdResult = await Promise.all<any>([
sequelize.query(
`update article set tag=REPLACE (tag,',${id "11"},',',') WHERE tag like '%${id}%'`,
{ transaction: t }
),
sequelize.query(
`update article set tag=REPLACE (tag,',${id "11"}','') WHERE tag like '%${id}%'`,
{ transaction: t }
),
sequelize.query(
`update article set tag=REPLACE (tag,'${id "11"},','') WHERE tag like '%${id}%'`,
{ transaction: t }
),
sequelize.query(
`update article set tag=REPLACE (tag,'${id "11"}','') WHERE tag like '%${id}%'`,
{ transaction: t }
),
]).then(res => {
// 实际删除了多少
let _tagCount = res.reduce((total, item) => {
return total item[0].affectedRows;
}, 0);
if (_tagCount != tagCount) {
console.log(`删除 ${id} 时 置换数量对不上${_tagCount}/${tagCount}`);
return false;
} else {
return true;
}
});
if (!(deleteTagCount && replaceTagIdResult)) {
console.log("回滚");
ctx.body = {
success: false,
message: "删除失败",
};
await t.rollback();
} else {
ctx.body = {
success: true,
message: "删除成功",
};
await t.commit();
}
});
export default router;
当然了,具体在Sequelize中使用事务处理的方法请在文档看,我这里也不说什么代码错误。
我在项目中也遇到了问题解决了好久:MyISAM不支持事务处理,请换成InnoDB