Ошибка тайм-аута при попытке блокировки таблицы в h2 - PullRequest
45 голосов
/ 12 ноября 2010

Я получаю следующую ошибку при определенном сценарии

Когда другой поток заполняет большое количество пользователей с помощью операции массовой загрузки, и я пытался просмотреть список всех пользователей на другой веб-странице.При запросе списка выдается следующая ошибка тайм-аута.Есть ли способ установить этот тайм-аут, чтобы я мог избежать этой ошибки тайм-аута.

Env: h2 (последний), 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

Ответы [ 7 ]

45 голосов
/ 12 ноября 2010

Да, Вы можете изменить время ожидания блокировки . Значение по умолчанию относительно низкое: 1 секунда (1000 мс).

Во многих случаях проблема заключается в том, что другое соединение заблокировало таблицу, и использование многоверсионного параллелизма также решает проблему (добавьте ;MVCC=true к URL базы данных).

39 голосов
/ 15 июня 2011

Я столкнулся с той же проблемой и, используя параметр "MVCC = true", решил ее.Вы можете найти больше объяснений об этом параметре в документации H2 здесь: http://www.h2database.com/html/advanced.html#mvcc

5 голосов
/ 28 октября 2012

Я хотел бы предложить, что если вы получаете эту ошибку, то возможно, вам не следует использовать транзакцию для вашей массовой операции базы данных . Вместо этого рассмотрите возможность выполнения транзакции для каждого отдельного обновления: имеет ли смысл рассматривать весь массовый импорт как транзакцию? Возможно нет. Если это так, то да, MVCC = true или больший тайм-аут блокировки - разумное решение.

Однако я думаю, что в большинстве случаев вы видите эту ошибку, потому что пытаетесь выполнить очень длинную транзакцию - другими словами, вы не знаете, что выполняете действительно длинную транзакцию. Это, безусловно, имело место для меня, и я просто больше заботился о том, как я записывал записи (без использования транзакций или с использованием меньших транзакций), и проблема тайм-аута блокировки была решена.

5 голосов
/ 07 ноября 2011

Для тех, у кого возникла эта проблема с интеграционными тестами (т. Е. Сервер обращается к базе данных h2, а интеграционный тест обращается к базе данных до вызова сервера, чтобы подготовить тест), добавив 'commit' к сценарию, выполненному до тестапроверяет, что данные находятся в базе данных перед вызовом сервера (без MVCC = true - что я нахожу немного «странным», если оно не включено по умолчанию).

1 голос
/ 21 мая 2015

Работа с DBUnit, H2 и Hibernate - та же ошибка, MVCC = true помогло, но я все равно получу ошибку для любых тестов после удаления данных.Что исправило эти случаи, так это фактический код удаления внутри транзакции:

Transaction tx = session.beginTransaction();
...delete stuff
tx.commit(); 
1 голос
/ 19 сентября 2011

Я получил эту проблему с PlayFramework

JPAQueryException произошла ошибка: ошибка при выполнении запроса от моделей. Страница, где имя =?: Тайм-аут при попытке заблокировать таблицу "PAGE"

Это закончилось бесконечным циклом, потому что у меня был

@ Before

без исключения, которое вызывало многократный вызов самой функции

@ Before (если = "getUser")

0 голосов
/ 06 октября 2018

У меня было MVCC = true в строке подключения, но все равно получала ошибку выше.Я добавил ;DEFAULT_LOCK_TIMEOUT=10000;LOCK_MODE=0 и проблема была решена

...