knex.js 是怎样解决 sqlite 事务并发问题的?

新手上路,请多包涵

我在学习 GitHub 上一个 node.js 后端项目时,他在用 knex.js 操作 sqlite 数据库,
我发现参照 knex 文档创建的写事务,似乎可以直接并行发起。

但在使用 sequelize 创建的事务就不行,会出现SQLITE BUSY 的锁死错误。

我查了一下 sqlite3 似乎是不支持写事务并发的,新一点的版本也支持读事务并发。

所以这就很令人困惑,sqlite 到底支不支持写事务并发?
kenx 创建的事务可以直接并发,是不是 kenx 的特性?
是不是 kenx 在内部把发起的事务丢到一个队列里,是伪并发,只是一个单线程?
如果是这样,在使用 sequelize 时,只能手动将事务丢到队列里,让它们依次执行?

下面是部分代码,完整的代码我传到 Github 上了,方便重现错误
https://github.com/Watanuki-Kimihiro/sqlite-busy

// byKnex

createSchema()
  .then(() => {
    let work = {
      id: 123456,
      title: 'Work_Title',
      circle: {id:12345, name:'Circile_Name'}
    };

    let promises = [];
    for (let i=1; i<10; i++) {
      let newWork = JSON.parse(JSON.stringify(work));
      newWork.id = work.id + i;
      promises.push(insertWorkMetadata(newWork));
    }

    return Promise.all(promises);
  })
  .then(() => {console.log("finished")})
  .catch((err) => {
    console.error(err);
  });

// bySequelize

const insertWorkMetadata = work => sequelize.transaction(t => {
  return Circle.findOrCreate({
    where: {id: work.circle.id},
    defaults: {name: work.circle.name},
    transaction: t
  })
    .then(([circle, created])=> {
      return circle.createWork({
        id: work.id,
        title: work.title,
      }, {transaction: t});
    });
});
  

sequelize.sync()
  .then(() => {
    let work = {
      id: 123456,
      title: 'Work_Title',
      circle: {id:12345, name:'Circile_Name'}
    };

    let promises = [];
    for (let i=1; i<10; i++) {
      let newWork = JSON.parse(JSON.stringify(work));
      newWork.id = work.id + i;
      promises.push(insertWorkMetadata(newWork));
    }

    return Promise.all(promises);
  })
  .then(() => {console.log("finished")})
  .catch((err) => {
    console.error(err);
  });
阅读 3.5k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题