SQLITE_BUSY 数据库被锁定 Java

3
我创建了一个利用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对于小型本地应用程序非常有用,在这种情况下,单例模式足以防止锁定。如果您的应用程序中有多个线程,则可以解决您的问题。我想你可能忘记了在某个地方关闭连接。我曾在一个旧应用程序上使用它,没有遇到这种问题。 - AxelH
当我尝试访问特定的表时,似乎出现了这个错误。所以我的问题是,我有一个查询语句,但我从未在某个地方关闭它? - Jose Ramon
每次出现在特定查询中的问题,我不确定原因! - Jose Ramon
我在SQLite浏览器中尝试了一下,它可以工作。也许是因为在我的软件会话期间我多次使用该表,导致该表仍然处于打开状态。 - Jose Ramon
我还观察到,如果您正在运行带有SELECT查询的Java程序,并且您打开了任何其他SQL编辑器,在其中尝试插入记录,那么SQLite文件仍会被锁定并显示此BUSY消息。解决方案是关闭SQL编辑器,以便文件锁定计数返回到0,并在Java程序中使用适当的ResultSet和PreparedStatement关闭代码。 - Rahul Saini
显示剩余2条评论
3个回答

4
每次打开SQLite数据库连接后,务必在处理结果等操作后关闭数据库连接。如果您已经有一个打开的数据库连接,并且尝试再次获取连接并尝试一些更新或插入查询,则系统不会给予许可并引发错误。请确保在使用完数据库连接后将其关闭。

1
这是一个与现有问题有些重复的问题,但这是一个很好的起点。因为SQLite只是一个读写文件系统上文件的库,而不是完整的SQL数据库,所以你应该只在一次时间打开一个连接。否则很容易陷入竞态条件。
对于本地测试,这应该是可以的,但对于期望有多个用户的任何复杂系统,您应该使用类似Postgre或MySQL的东西。

是的,我知道这个问题。然而有时候问题只会在运行我的软件的一个实例时发生。虽然我有几个选择插入和更新查询。问题出现在特定的表中。我能控制一下对数据库中那个表的访问吗? - Jose Ramon
使用MySql作为应用程序的数据库需要安装它,如果你只是想使用SQL语法在本地文件中存储一些数据,这并不是最好的选择。 - AxelH

1
你的try catch写错了,你试图在try块中关闭ResultSet和Statemnt而不是在finally块中。这可能会导致泄漏。
你应该像这样做,在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可能是问题的原因。(这个名称并不令人放心,因为整个应用程序应该只有一个连接) - AxelH
有没有办法找出导致我的问题的确切原因? - Jose Ramon
@JoseRamon,如果出现异常,您永远不会关闭结果集或语句。这是一个常见的错误,您应该纠正它。 - AxelH
我的问题出现在catch中,因为我还有system.exit :) - Jose Ramon
在我的情况下,关闭应用程序比在我的数据库中有空字段更好。 - Jose Ramon
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接