sqflite 数据库被锁定 flutter - 警告数据库已被锁定

sqflite database getting locked flutter - Warning database has been locked

我在我的 flutter 项目中使用 SQLite 并试图找出数据库锁定问题,在我的场景中,用户每天尝试下载一次新数据,如果该记录存​​在,它将更新或插入一个新纪录。我的问题是,即使我正在使用事务和批处理,我也遇到了数据库锁定错误,我唯一能想到的问题是 getSongList() 调用,因为它多次从该事务或批处理中调用数据库,但这是读取调用,我的代码似乎在批量提交期间失败。

buildDB1(List<MusicData> _list, int version) async {
    await openDb();
    try {
      _database.transaction((txn) async {
        Batch batch = txn.batch();
        for (var i = 0; i < _list.length; i++) {
          // buildBatch(_list[i]);
          MusicData musicData = _list[i];
          int id = musicData.id;
          if (musicData.pdfpage == 0 || musicData.pdfpage == null) {
            PDFPAGE = "0";
          } else {
            PDFPAGE = (musicData.pdfpage).toString();
          }
          if (musicData.linkid == 0 || musicData.linkid == null) {
            LINKID = "0";
          } else {
            LINKID = (musicData.linkid).toString();
          }
          // PDFPAGE = musicData.pdfpage as String;
          // LINKID = musicData.linkid as String;
          TITLE = musicData.title;
          ALBUM = musicData.album;
          SONGURL = musicData.songURL;
          HINDINAME = musicData.hindiName;
          MNAME = musicData.mname;
          MSIGN = musicData.msign;
          OTHER1 = musicData.other1;
          OTHER2 = musicData.other2;
          ENAME = musicData.ename;
          ESIGN = musicData.esign;
          LANGUAGE = musicData.language;
          SONGTEXT = musicData.songtext;
          Future<List<MusicData>> list1 =
              getSongList("select * from songs where id=$id");
          List<MusicData> list = await list1;
          if (list.length != 0) {
            String updateSQL =
                "UPDATE SONGS SET pdfpage = $PDFPAGE, linkid = $LINKID, title = '$TITLE', album = '$ALBUM', songURL = '$SONGURL', hindiName = '$HINDINAME', mname = '$MNAME', msign = '$MSIGN', other1 = '$OTHER1', other2 = '$OTHER2', ename = '$ENAME', esign = '$ESIGN', language = '$LANGUAGE',songtext = '$SONGTEXT' WHERE id = $ID";
            batch.rawUpdate(updateSQL);
            // _database.rawUpdate(
            //     "UPDATE SONGS SET pdfpage = ?, linkid = ?, title = ?, album = ?, songURL = ?, hindiName = ?, mname = ?, msign = ?, other1 = ?, other2 = ?, ename = ?, esign = ?, language = ?,songtext = ? WHERE id = ?",
            //     [
            //       musicData.id,
            //       musicData.pdfpage,
            //       musicData.linkid,
            //       musicData.title,
            //       musicData.album,
            //       musicData.songURL,
            //       musicData.hindiName,
            //       musicData.mname,
            //       musicData.msign,
            //       musicData.other1,
            //       musicData.other2,
            //       musicData.ename,
            //       musicData.esign,
            //       musicData.language,
            //       musicData.songtext
            //     ]);

            print("Record updated in db $id");
            // _database.close();
          } else {
            String insertSQL =
                "INSERT INTO SONGS (pdfpage, linkid, title,album,songURL,hindiName,mname,msign,other1,other2,ename,esign,language,songtext,isfav) VALUES ($PDFPAGE,$LINKID,'$TITLE','$ALBUM','$SONGURL','$HINDINAME','$MNAME','$MSIGN', '$OTHER1','$OTHER2','$ENAME','$ESIGN','$LANGUAGE','$SONGTEXT',0)";
            batch.rawInsert(insertSQL);
            // _database.insert('SONGS', musicData.toMap());
            print("Record inserted in db $id");
          }
        }
        Future<List> result = batch.commit();
      });
      SharedPreferences prefs = await SharedPreferences.getInstance();
      await prefs.setInt('dbversion', version);
    } catch (e) {
      print(e);
    }
  }

getSongList 应该采用事务参数。基本上在事务期间的任何数据库调用中使用 txn 而不是 _database。否则它会挂起并且警告是正确的。

此外,您可能遇到了一些竞争条件,因为您没有在交易结束前等待 batch.commit。您可以尝试更换:

Future<List> result = batch.commit();

来自

await batch.commit();

使用 pedantic 可以警告您此处缺少 await。