【问题标题】:SQLITE_BUSY the database is locked javaSQLITE_BUSY 数据库被锁定 java
【发布时间】:2016-09-15 11:55:15
【问题描述】:

我创建了一个使用 sqlite 数据库的 java 软件。整个数据库运行顺利,但是在运行应用程序一段时间后,我收到以下消息(来自 try catch 块):

java.sql.SQLException: [SQLITE_BUSY] 数据库文件被锁定(数据库被锁定)

每次出现异常时我都通过关闭软件解决了我的问题。但是有没有办法关闭我的数据库而不是每次都关闭软件?

我有很多疑问,但我的问题总是出现在一个特定的点上:

        try {
            String query = "select * from StudentsSession where userId=? and course=? and level=?";
            PreparedStatement pst = connectionUsers.prepareStatement(query);
            pst.setString(1, saveUser.getText());
            pst.setString(2, textSubjectQTest);
            st.setString(3, showCurrentLevelLabel.getText());
            ResultSet rs = pst.executeQuery();
            while (rs.next()) {
                count = count + 1;
            }
            pst.close();
            rs.close();

        } catch (Exception a) {
            System.out.println(a);
        }
        try {
            String countS, tmpS;
            countS = String.valueOf(count);
            sessionId.setText(countS);
            long unixTime = System.currentTimeMillis() / 1000L;
            tmpS = String.valueOf(unixTime);
            date.setText(tmpS);
            course.setText(textSubjectQTest);

            String query = "insert into StudentsSession (userId,date,course,level,trial,score) values (?,?,?,?,?,-1)";
            PreparedStatement pst = connectionUsers.prepareStatement(query);
            pst.setString(1, saveUser.getText());
            pst.setString(2, tmpS);
            pst.setString(3, textSubjectQTest);
            pst.setString(4, showCurrentLevelLabel.getText());
            pst.setString(5, countS);
            pst.executeUpdate();
            pst.close();

        } catch (Exception a) {

            System.out.println(a);
            System.exit(0);
        }

        String file1 = "";
        ResultSet ts4;
        try {

            sessionId3 = "";
            String query3 = "select * from studentssession where userid = ?  and course = ? and level = ?";
            PreparedStatement pst__1 = connectionUsers.prepareStatement(query3);
            pst__1.setString(1, saveUser.getText());
            pst__1.setString(2, textSubjectQTest);
            pst__1.setString(3, showCurrentLevelLabel.getText());
            ts4 = pst__1.executeQuery();

            while (ts4.next()) {
                sessionId3 = ts4.getString("sessionId");
            }
            pst__1.close();
            ts4.close();
            obj = new CaptureVideoFromWebCamera();

            file1 = "videos/" + userTextFieldS.getText();

            file1 = file1 + "_" + sessionId3;
            file1 = file1 + ".wmv";

            obj.start(file1);

        } catch (Exception e4) {
            e4.getCause();
        }

有时这段代码会引发异常。

【问题讨论】:

  • SQlite 对于小型本地应用程序很有用,在这种情况下,Singleton 足以防止锁定。如果您的应用程序中有多个线程,那将解决您的问题。我会说你忘了在某个地方关闭你的连接。我在旧应用上使用它时没有遇到此类问题。
  • 当我尝试访问特定表时似乎会出现此错误。所以我的问题是我有一个查询语句我从来没有在某个地方关闭它?
  • 我的问题每次都出现在特定的查询中,我不知道为什么!
  • 我在 sqlite 浏览器中尝试过,它可以工作。也许是因为我在软件会话期间多次使用该表,所以该表保持打开状态。
  • 你可以使用它10亿次,如果你正确关闭I/O,它是没有问题的。您能否添加更多代码,如果您使用事务,您如何管理查询中的异常,如果您关闭所有内容...

标签: java sqlite


【解决方案1】:

每次打开与 SQLite 数据库的连接时,请确保在处理结果等后关闭数据库连接。如果您已经打开了与数据库的连接并且尝试再次获取连接并尝试一些UpdateInsert 查询,系统不会给予权限,会报错。

【讨论】:

    【解决方案2】:

    您的 try catch 错误,您尝试关闭 try 块中的 ResultSetStatemnt 而不是 finally 块。这可能会导致泄漏。

    你应该这样做,在最后。

    PreparedStatement pst  = null;
    ResultSet rs = null;
    try {
            pst = connectionUsers.prepareStatement(query);
            ...  
            rs = pst.executeQuery();
            ...                    
        } catch (Exception a) {
            a.printStackTrace();
        } finally {
            if(rs != null){
                 try{
                      rs.close();
                 } catch(Exception e){
                     e.printStackTrace();
                 }
            }
            if(pst != null){
                try{
                    pst.close();
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    

    或者您可以查看 Try-with-resource。

    这可能是一个原因。

    【讨论】:

    • 那么我应该对代码中的每个查询都执行相同的操作吗?
    • 如果这不是原因,那么connectionUser 可能是原因。 (这个名字并不让人放心,因为整个应用程序应该只有 1 个连接)
    • 有没有办法检索到底是什么导致了我的问题?
    • @JoseRamon,哦,是的,如果发生异常,您永远不会关闭结果集或语句。这是您应该纠正的常见错误。
    • 对于确切的原因,您应该更具体地说明您为使其崩溃所做的测试,在这个 4 查询块中。我只能假设没有所有信息的原因;)
    【解决方案3】:

    与现有问题类似,但 this is a good starting point。因为 SQLite 只是一个在文件系统上读取和写入文件的库,而不是完整的 SQL 数据库,所以您实际上应该一次只打开一个连接。否则很容易陷入竞争状态。

    对于本地测试,它应该没问题,但对于期望多个用户的任何复杂系统,您应该使用 Postgre 或 MySQL 之类的东西。

    【讨论】:

    • 是的,我知道这一点。但是,有时仅通过运行我的软件的一个实例就会出现问题。我有几个选择插入和更新查询。问题出现在特定表中。我可以以某种方式控制对我的数据库表的访问吗?
    • 使用 MySql 作为应用程序必须安装它,如果您只想能够使用 SQL 语法在本地文件中存储一些数据,则不是最佳选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2019-10-07
    相关资源
    最近更新 更多