V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
watanuki
V2EX  ›  Node.js

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

  •  
  •   watanuki · 2020-08-16 15:51:47 +08:00 · 2627 次点击
    这是一个创建于 1560 天前的主题,其中的信息可能已经有所发展或是发生改变。

    虽然我知道 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);
      });
    
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2703 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:58 · PVG 17:58 · LAX 01:58 · JFK 04:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.