37

如果我对我的网络应用程序运行多个线程,我会得到:

java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)
    at org.sqlite.DB.newSQLException(DB.java:383)
    at org.sqlite.DB.newSQLException(DB.java:387)
    at org.sqlite.DB.execute(DB.java:339)
    at org.sqlite.PrepStmt.executeQuery(PrepStmt.java:75)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)

我知道只有一个线程可以写入 sqlite 数据库,但我只是从数据库中读取。那么为什么我会收到此错误消息?

顺便说一句:我的连接池如下所示:

<bean class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" id="dataSource">
    <property name="driverClassName" value="${database.driverClassName}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.username}" />
    <property name="password" value="${database.password}" />
    <property name="initialSize" value="1" />
    <property name="maxActive" value="2" />
    <property name="maxIdle" value="1" />
    <property name="poolPreparedStatements" value="true" />
</bean>

设置为:Java 1.6、Tomcat 7.0.34、Spring 3.2、Hibernate 3.6.9 和 sqlite3 3.7.2

问候罗杰

4

11 回答 11

27

经过一番谷歌搜索后,我发现在连接到 SQLite 时使用多个连接是一种不好的做法。看

http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking

将您的 poolsize maxactive 设置为 1 并尝试一下。

于 2012-12-15T11:48:36.017 回答
12

您的应用程序应该只有一个连接。您可以使用它来确保。

public class SqliteHelper {
private static Connection c = null;
public static Connection getConn() throws Exception {
    if(c == null){
    Class.forName("org.sqlite.JDBC");
    c = DriverManager.getConnection("jdbc:sqlite:D:/test.db");
    }
    return c;
    }
}
于 2014-06-15T18:27:27.270 回答
9

另请注意,如果您不小心忘记关闭连接,则可能会发生这种情况:

Connection connection;
try {
  Statement statement = connection.createStatement();
  ResultSet resultSet = statement.executeQuery(QUERY);
  if (resultSet.next()) { /* do something */ }
catch (SQLException e) { /* handle exception */ }
finally {
  if (connection != null) {
    try {
      connection.close(); // <-- This is important
    } catch (SQLException e) {
      /* handle exception */
    }
  }
}

虽然一旦服务器启动,第一个数据库连接可能会正常工作,但后续查询可能不会,这取决于连接池的配置方式。

于 2014-10-21T20:12:32.000 回答
2

每次建立连接时,请确保在工作完成后关闭它,它对我有用,就像您正在使用

Connection con = null;
PreparedStatement pst = con.prepareStatement("...query... "); 
/*
 do some stuff 
*/
pst.executeQuery();
pst.close();
con.close();
于 2018-05-01T05:15:48.307 回答
1

我遇到了同样的问题,即使所有连接、结果集和语句都已关闭,我仍然遇到错误。我的问题是使用 Intellij 中的 DB 浏览器插件来可视化和管理表。从这个工具断开数据库解决了这个问题。因此,请确保没有外部工具连接到数据库并锁定表。

于 2020-11-10T07:52:53.373 回答
1

在我的情况下,后台有线程使用 sqlite 连接,这导致了这个错误。

  1. 关闭 sqlitebrowser
  2. 关闭电子应用程序(可能需要重新启动)
  3. 重新运行你的程序。
于 2021-04-18T11:41:02.863 回答
1

对于在 WSL2 中遇到问题的任何人:

当我使用 WSL2 和 Datagrip 时发生在我身上,即使数据库不忙。

事实证明,Datagrip 试图通过 Windows 的 sqlite3 连接到 WSL2 中存在的数据库文件。

将文件从 WSL2 移动到 Windows 文件目录似乎可以解决此问题

于 2022-01-05T16:51:26.810 回答
0

对我来说,问题是我打开了太多的会话所以我将我的 DAO 类中的会话字段设为静态

于 2018-12-07T16:49:39.640 回答
0

感谢 bowman han,我在他的解决方案中添加了一段代码,它对我有用。

private static Connection c = null;
public static Connection connect() throws Exception {

    if (c == null) {
        c = (Connection) DriverManager.getConnection(url);
    } else {
        c.close();
        c = (Connection) DriverManager.getConnection(url);
    }
    return c;
}
于 2019-11-09T11:21:22.017 回答
0

您打开了另一个包含数据库的应用程序,请尝试关闭该应用程序并再次运行您的程序。这对我有用

于 2021-08-26T23:23:12.107 回答
-2

尝试@Transactional(readonly=true)那些只做读取的方法。也许这对你有用。

于 2012-12-15T09:30:48.777 回答