颤动:警告数据库已锁定0:00:10.000000。在Android

时间:2020-09-15 10:12:17

标签: sqlite flutter sqflite

我在这个错误上停留了一个月,无法通过Google找到任何解决方案。 我构建了一个需要在线和离线均可使用的聊天应用,后端是NodeJS 下面的代码将所有仍待处理的消息发送到目标设备

  async function _worker(socket) {
    console.log('worker running...')
    await connect.then(async (db) => {

        // When user A sent message to user B but user B is offline so server need to sync this message to user B
        Message.find({ isDeliver: 0 }).then(async (m) => {
            if (m.length > 0) {
                for (let i = 0; i < m.length; i++) {
                    let sender = m[i].sender;
                    let receiver = m[i].receiver;
                    let online = await checkUserOnline(socket, receiver);
                    if (online) {
                        let to_user_socket_id = getSocketIDfromMapForthisUser(`${receiver}`)
                        sendToConnectedSocket(socket, to_user_socket_id, "send_message_to_device", m[i]);
                    }
                }
            }
        });

         // When user A sent a message to user B and user B is offline but when user B is online and message delivered to user B and user A is offline server need to sync this message status to update for user A
         Message.find({ isDeliver: 1 }).then(async (m) => {
            if (m.length > 0) {
                for (let i = 0; i < m.length; i++) {
                    let sender = m[i].sender;
                    let receiver = m[i].receiver;
                    let online = await checkUserOnline(socket, sender);
                    if (online) {
                        let to_user_socket_id = getSocketIDfromMapForthisUser(`${sender}`)
                        sendToConnectedSocket(socket, to_user_socket_id, "send_message_deliver", m[i]);
                    }
                }
            }
        });

        // When user A sent a message to user B and user B is offline but when user B is online and read the message and user A is offline server need to sync this message status to update for user A
        Message.find({ isRead: 1 }).then(async (m) => {
            if (m.length > 0) {
                for (let i = 0; i < m.length; i++) {
                    let sender = m[i].sender;
                    let receiver = m[i].receiver;
                    let online = await checkUserOnline(socket, sender);
                    if (online) {
                        let to_user_socket_id = getSocketIDfromMapForthisUser(`${sender}`)
                        sendToConnectedSocket(socket, to_user_socket_id, "send_message_read", m[i]);
                    }
                }
            }
        });

    });
 }

及以下是处理服务器事件的方法:

套接字

setOnServerSendDeliver(Function  onServerSendDeliver) {
    _socket.on('send_message_deliver', (data) {
        onServerSendDeliver(data);
    });
  }

  setOnServerSendRead(Function  onServerSendRead) {
    _socket.on('send_message_read', (data) {
      onServerSendRead(data);
    });
  }

  setOnServerSendToDevice(Function onServerSendToDevice) {
    _socket.on('send_message_to_device', (data) {
      onServerSendToDevice(data);
    });
  }

方法

 onServerSendDeliver(data) async {
    MessageModel message = MessageModel.fromJson(jsonDecode(data));
    await G.dbService.updateDeliver(message);
    G.socketUtils.sendDeliveryDone(message, new UserModel(id: message.sender));
    refreshMessage();
  }

  onServerSendRead(data) async {
    MessageModel message = MessageModel.fromJson(jsonDecode(data));
    await G.dbService.updateRead(message.chatId);
    G.socketUtils.sendReadDone(message, new UserModel(id: message.sender));
    refreshMessage();
  }

  onServerSendToDevice(data) async {
    MessageModel message = MessageModel.fromJson(jsonDecode(data));
    ChatModel chat = new ChatModel();
    chat.id = message.chatId;
    chat.fromId = message.sender;
    chat.toId = message.receiver;
    chat.message = message.content;
    await G.dbService.chatOperation(chat);
    await G.dbService.insertMessage(message);
    await G.dbService.updateDeliver(message);
    G.socketUtils.sendDelivery(message, new UserModel(id: message.sender));
    refreshMessage();
  } 

在我设置的服务器中

setInterval(_worker, 1500, socket);

加载检查消息并发送到终端设备

和我的数据库功能

Future<String> updateRead(String chatId) async {
    Database db = await database;
    try {
      await db.transaction((txn) async {
        return await txn.rawUpdate(
            "UPDATE messages SET isRead = 1, isSend = 1, isDeliver = 1 WHERE chatId = ? AND status = 0",
            [chatId]);
      });

      await db.transaction((txn) async {
        return await txn.rawUpdate(
            "UPDATE chats SET isRead = 1, isSend = 1, isDeliver = 1 WHERE id = ? AND status = 0",
            [chatId]);
      });
    } catch (e) {
      print(e.toString());
    }
    return chatId;
  }

  Future<String> updateDeliver(MessageModel message) async {
    Database db = await database;
    String id;
    try {
      id = message.id;
      await db.transaction((txn) async {
        return await txn.rawUpdate(
            "UPDATE messages SET isDeliver = 1 WHERE id = ? AND status = 0",
            [message.id]);
      });

      await db.transaction((txn) async {
        return await txn.rawUpdate(
            "UPDATE chats SET isDeliver = 1 WHERE id = ? AND status = 0",
            [message.chatId]);
      });
    } catch (e) {
      print(e.toString());
    }
    return id;
  } 

iOS运行正常,但在android上我总是遇到此错误,并且我的应用卡住了:

颤振:警告数据库已锁定0:00:10.000000。确保在交易期间始终使用交易对象进行数据库操作

任何帮助都是合适的

更新

我试图将数据库功能修改为:

Future<String> updateDeliver(MessageModel message) async {
    Database db = await database;
    String id;
    try {
      id = message.id;
      await db.transaction((txn) async {
        var batch = txn.batch();
        batch.rawUpdate(
            "UPDATE messages SET isDeliver = 1 WHERE id = ? AND status = 0",
            [message.id]);
        batch.rawUpdate(
            "UPDATE chats SET isDeliver = 1 WHERE id = ? AND status = 0",
            [message.chatId]);
        batch.commit();
      });
    } catch (e) {
      print(e.toString());
    }
    return id;
  }

但我仍然面临同样的问题

1 个答案:

答案 0 :(得分:0)

确保在事务中await使用任何异步方法:

await batch.commit();

当您忘记了await时,应该使用学究的(或适当的棉绒)警告。

是的,不要为单个操作创建事务,而是尝试将事务中的操作分组(如果可以的话,还可以批量)。

您也可以turn on logging来确保您没有进行太多的sqlite查询。