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。
我在我的 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。