电解熔融氧化铝
  • 1
  • 新人请关照

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);
  });
阅读 130
评论 3月31日提问
    撰写回答

    登录后参与交流、获取后续更新提醒