web-dev-qa-db-fra.com

Erreur de délai d'attente lors de la tentative de verrouillage de la table dans h2

J'obtiens l'erreur suivante dans un certain scénario

Lorsqu'un autre thread remplissait beaucoup d'utilisateurs via l'opération de téléchargement en bloc et que j'essayais d'afficher la liste de tous les utilisateurs sur une page Web différente. La requête de liste renvoie l'erreur de délai d'attente suivante. Existe-t-il un moyen de définir ce délai afin que je puisse éviter cette erreur de délai?.

Env: h2 (dernière), Hibernate 3.3.x

Caused by: org.h2.jdbc.JdbcSQLException: Timeout trying to lock table "USER"; SQL statement:

[50200-144]

    at org.h2.message.DbException.getJdbcSQLException(DbException.Java:327)
    at org.h2.message.DbException.get(DbException.Java:167)
    at org.h2.message.DbException.get(DbException.Java:144)
    at org.h2.table.RegularTable.doLock(RegularTable.Java:482)
    at org.h2.table.RegularTable.lock(RegularTable.Java:416)
    at org.h2.table.TableFilter.lock(TableFilter.Java:139)
    at org.h2.command.dml.Select.queryWithoutCache(Select.Java:571)
    at org.h2.command.dml.Query.query(Query.Java:257)
    at org.h2.command.dml.Query.query(Query.Java:227)
    at org.h2.command.CommandContainer.query(CommandContainer.Java:78)
    at org.h2.command.Command.executeQuery(Command.Java:132)
    at org.h2.server.TcpServerThread.process(TcpServerThread.Java:278)
    at org.h2.server.TcpServerThread.run(TcpServerThread.Java:137)
    at Java.lang.Thread.run(Thread.Java:619)
    at org.h2.engine.SessionRemote.done(SessionRemote.Java:543)
    at org.h2.command.CommandRemote.executeQuery(CommandRemote.Java:152)
    at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.Java:96)
    at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.Java:342)
    at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.Java:208)
    at org.hibernate.loader.Loader.getResultSet(Loader.Java:1808)
    at org.hibernate.loader.Loader.doQuery(Loader.Java:697)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.Java:259)
    at org.hibernate.loader.Loader.doList(Loader.Java:2228)
    ... 125 more
43
user339108

Oui, vous pouvez modifier le délai de verrouillage . La valeur par défaut est relativement basse: 1 seconde (1000 ms).

Dans de nombreux cas, le problème est qu'une autre connexion a verrouillé la table et que l'utilisation de l'accès simultané multi-version résout également le problème (ajoutez ;MVCC=true à l'URL de la base de données).

42
Thomas Mueller

J'ai rencontré le même problème et en utilisant le paramètre "MVCC = true", le problème a été résolu. Vous trouverez plus d’informations sur ce paramètre dans la documentation H2 ici: http://www.h2database.com/html/advanced.html#mvcc

39
Bruno ARLIGUY

Je voudrais suggérer que si vous obtenez cette erreur, alors vous ne devriez peut-être pas utiliser une transaction sur votre opération de base de données en bloc . Envisagez plutôt d'effectuer une transaction sur chaque mise à jour individuelle: est-il judicieux de considérer une importation en bloc comme une transaction? Probablement pas. Si c'est le cas, alors oui, MVCC = true ou un délai de verrouillage plus long est une solution raisonnable. 

Cependant, je pense que dans la plupart des cas, vous voyez cette erreur parce que vous essayez d'effectuer une très longue transaction. En d'autres termes, vous ne savez pas que vous effectuez une très longue transaction. Ce fut certainement le cas pour moi et j'ai simplement pris plus de précautions sur la manière dont j'écrivais des enregistrements (en n'utilisant aucune transaction ou en utilisant des transactions plus petites) et le problème du délai de verrouillage a été résolu. 

5
Tom Carchrae

Pour ceux qui rencontrent ce problème avec les tests d'intégration (le serveur accède à la base de données h2 et un test d'intégration accède à la base de données avant d'appeler le serveur pour préparer le test), ajouter un 'commit' au script exécuté avant que le test ne s'assure que les données sont dans la base de données avant d'appeler le serveur (sans MVCC = true - ce que je trouve un peu "bizarre" si ce n'est pas activé par défaut).

4
unludo

Travailler avec DBUnit, H2 et Hibernate - même erreur, MVCC = true m'a aidé, mais j'obtiendrais quand même l'erreur pour tous les tests après la suppression des données. Ce qui a résolu ces problèmes, c’était de placer le code de suppression réel dans une transaction:

Transaction tx = session.beginTransaction();
...delete stuff
tx.commit(); 
1
Boyko

J'ai eu ce problème avec PlayFramework 

JPAQueryException s'est produite: erreur lors de l'exécution de la requête à partir de models.Page où name =?: le délai d'attente pour verrouiller la table "PAGE"

Cela a fini par être une boucle infinie parce que j'avais un

@Avant

sans un sauf si ce qui a amené la fonction à s'appeler à plusieurs reprises

@Avant (sauf si "getUser")

1
David d C e Freitas

J'avais MVCC = true dans ma chaîne de connexion, mais je rencontrais toujours l'erreur ci-dessus. J'avais ajouté ;DEFAULT_LOCK_TIMEOUT=10000;LOCK_MODE=0 et le problème a été résolu

0
Ev.Rei.