web-dev-qa-db-fra.com

L'obtention du fichier de base de données [SQLITE_BUSY] est verrouillée avec les instructions select

Si je lance plusieurs threads sur mon application Web, je reçois:

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)

Je sais qu'un seul thread peut écrire dans une base de données sqlite mais je ne fais que lire dans la base de données. Alors, pourquoi est-ce que je reçois ce message d'erreur?

BTW: Mon pool de connexion ressemble à ceci:

<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>

La configuration est la suivante: Java 1.6, Tomcat 7.0.34, Spring 3.2, Hibernate 3.6.9 et sqlite3 3.7.2. 

Cordialement Roger

21
rogergl

Après quelques recherches sur Google, j’ai trouvé que c’était une mauvaise pratique d’utiliser plusieurs connexions lors de la connexion à SQLite. Voir

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

Réglez votre pool maxactive à 1 et essayez-le.

16
sorencito

Il ne devrait y avoir qu’UNE SEULE connexion avec votre application ... vous pouvez l’utiliser pour vous assurer.

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;
    }
}
11
bowman han

Notez également que cela peut se produire si vous oubliez accidentellement de fermer votre connexion:

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

Bien que la première connexion à la base de données puisse fonctionner correctement une fois le serveur démarré, les requêtes suivantes peuvent ne pas l'être, en fonction de la configuration du pool de connexions.

5
johanwannheden

Chaque fois que vous établissez une connexion, assurez-vous de la fermer une fois le travail terminé. Cela a fonctionné pour moi comme si vous utilisiez

Connection con = null;
PreparedStatement pst = con.prepareStatement("...query... "); 
/*
 do some stuff 
*/
pst.executeQuery();
pst.close();
con.close();
1
maheshmnj

Pour moi, le problème était que j'ouvrais trop de sessions. J'ai donc rendu le champ de session statique dans ma classe DAO. 

0
Soundous Bahri