2012-12-15 68 views
16

如果我跑对我的web应用程序的多个线程我得到:入门[SQLITE_BUSY]数据库文件被锁定与select语句

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数据库,但我只从数据库读取。那么,为什么我会得到这个错误消息呢?

BTW:我的连接池是这样的:

<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,春季3.2的Hibernate 3.6.9和3.7.2 sqlite3的

问候 罗杰

+0

可能重复[SQLITE \ _BUSY数据库文件被锁定(数据库被锁定)在检票中](http://stackoverflow.com/questions/8559623/sqlite-busy-the-database-file-is-locked-数据库被锁定在检票口) – Stephan

回答

15

经过一些Google搜索后,我发现在连接到SQLite时使用多个连接是不好的做法。见

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

设置你的poolsize maxactive 1和尝试。

+0

是的。但我仍然不明白为什么文件被锁定,尽管只有select语句被执行。 – rogergl

+0

@rogergl:尝试获取与SQLiteOpenHelper#getReadableDatabase()的连接。链接:http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html – sorencito

0

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

+0

这没有帮助 – rogergl

+0

好吧,看看我的新答案。 – sorencito

+0

这也是SQLite文档中推荐的几个步骤之一,以减少这种情况的发生。第一步是确保一切都关闭。还应该检查数据库是否支持线程(默认为打开)FULLMUTEX – oden

9

应用程序应该只有一个连接。 你可以用这个来确保。

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; 
    } 
} 
2

还要注意的是,这可能发生,如果你不小心忘记关闭您的连接:

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 */ 
    } 
    } 
} 

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