用 sequelize.js 操作 sqlite3 数据库在并发写事务时,出现 "SQLITE_BUSY" 的报错,但在用 knex.js 时就没有出现这个错误,问题到底出在哪里?

2020-08-16 15:51:47 +08:00
 watanuki

虽然我知道 sqlite 数据库本身是不支持并发写事务的,应该是 knex.js 在执行的时候做了相应处理。但我在 knex.js 和 sequelize.js 的文档里都没找到关于 sqlite 该如何处理并发写事务的说明。

所以,让我困惑的问题有两个:

  1. knex.js 和 sequelize.js 在处理 sqlite 数据库的并发写事务时的区别是什么?
  2. 如果选择使用 sequelize.js 操作 sqlite 数据库,又该如何处理并发写事务?

有熟悉 sequelize 和 knex.js 这两个库的 v 友吗?

下面是部分代码段,为了方便重现报错,我写了一个小 demo,https://github.com/Watanuki-Kimihiro/sqlite-busy

byKnex

// sqlite-busy/byKnex/db.js
const insertWorkMetadata = work => knex.transaction(trx => trx.raw(
  // insert or ignore into `t_circle` (`id`, `name`) values (12345, 'Circile_Name')
  trx('t_circle')
    .insert({
      id: work.circle.id,
      name: work.circle.name,
    }).toString().replace('insert', 'insert or ignore'),
)
  .then(() => trx('t_work')
    .insert({
      id: work.id,
      title: work.title,
      circle_id: work.circle.id
    })));


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

// sqlite-busy/bySequelize/db.js
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);
  });
2503 次点击
所在节点    Node.js
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/698698

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX