2010-11-12 5 views
41

je reçois l'erreur suivante dans un certain scénarioerreur Délai d'attente essayant de verrouiller la table en h2

Lorsqu'un autre thread est peuplait beaucoup d'utilisateurs via l'opération de chargement en vrac et je tente de voir 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. Est-il possible de définir ce délai d'expiration afin que je puisse éviter cette erreur de délai d'attente.

Env: h2 (dernier), Mise en veille prolongée 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 

Répondre

39

Oui, you can change the lock timeout. La valeur par défaut est relativement faible: 1 seconde (1000 ms).

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

+0

Je positionniez le délai d'attente sur l'URL du pilote, mais je reçois toujours la même erreur car l'opération ci-dessus prend probablement environ 30 secondes. Je ne veux pas que les autres utilisateurs qui utilisent cette page voient un crash pendant ce temps. Cela signifie-t-il que je devrai régler le délai d'attente à plus de 30 secondes pour éviter ce problème? Comment trouver des problèmes spécifiques aux performances si le délai d'attente est défini sur un grand nombre – user339108

+0

La transaction prend-elle réellement 30 secondes? Cela me semble un peu long. Est-il possible de diviser la transaction en plusieurs transactions plus petites (par exemple 0,5 seconde chacune)? –

+6

L'utilisation du paramètre "MVCC = true" est la solution, changer le timeout ne résout pas ce problème. –

38

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

+1

C'est la bonne réponse, changer le timeout de verrouillage n'est pas la solution. –

+1

@BananHunt cela dépend vraiment. Tout ce que vous pouvez dire, c'est que ce n'est pas la solution pour votre cas d'utilisation. –

+0

@ThomasMueller Avons-nous un inconvénient si nous utilisons "MVCC = true"? –

1

J'ai eu ce problème avec le play framework

JPAQueryException est survenue: Erreur lors de l'exécution de la requête models.Page où name =: Délai d'attente essayer de verrouiller la table « PAGE »

Il a fini d'être une boucle infinie de toutes sortes parce que j'avais

@Before

sans moins que ce qui a causé la fonction à appeler à plusieurs reprises se

@Before (à moins = "getUser")

3

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

5

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

Cependant, je pense que dans la plupart des cas, vous voyez cette erreur car vous essayez d'effectuer une transaction très longue - en d'autres termes, vous ne savez pas que vous effectuez une transaction très longue. C'était certainement le cas pour moi-même et j'ai simplement pris plus de soin sur la façon dont j'écrivais des enregistrements (soit en n'utilisant aucune transaction ou en utilisant des transactions plus petites) et le problème du timeout de verrouillage a été résolu.

1

Travailler avec DBUnit, H2 et Hibernate - même erreur, MVCC = true a aidé, mais j'obtiendrais quand même l'erreur pour tous les tests suivant la suppression des données.Ce qui fixe ces cas enveloppait le code de suppression réelle à l'intérieur d'une transaction:

Transaction tx = session.beginTransaction(); 
...delete stuff 
tx.commit(); 
Questions connexes