我们使用h2started作为数据库服务器进程,监听标准tcp/ip端口9092。
我们的应用程序使用连接池部署在tomcat中。我们在空闲时间进行净化,最终导致所有与h2的连接关闭。当应用程序再次尝试打开与h2的连接时,我们不时会看到错误:
SCHEDULERSERVICE schedule: Exception: Database may be already in use: "Waited for database closing longer than 1 minute". Possible solutions: close all other connection(s); use the server mode [90020-199]
org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database may be already in use: "Waited for database closing longer than 1 minute". Possible solutions: close all other connection(s); use the server mode [90020-199]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:617)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:427)
at org.h2.message.DbException.get(DbException.java:205)
at org.h2.message.DbException.get(DbException.java:181)
at org.h2.engine.Engine.openSession(Engine.java:209)
at org.h2.engine.Engine.createSessionAndValidate(Engine.java:178)
at org.h2.engine.Engine.createSession(Engine.java:161)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:160)
at java.lang.Thread.run(Thread.java:748)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:617)
at org.h2.engine.SessionRemote.done(SessionRemote.java:607)
at org.h2.engine.SessionRemote.initTransfer(SessionRemote.java:143)
at org.h2.engine.SessionRemote.connectServer(SessionRemote.java:431)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:317)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:169)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:148)
at org.h2.Driver.connect(Driver.java:69)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
当tomcat连接池关闭所有空闲连接(未使用)并且一个仍在使用中的连接随后被关闭时,就会出现问题。
下次尝试打开新连接失败,等待一段时间后重试成功。
在什么情况下会发生这种例外情况?
例外是什么意思?
有什么建议可以用来避免这个问题吗?
在我看来,h2会在最后一个连接关闭后关闭数据库。
数据库何时关闭?
如何控制数据库关闭?
thx预支thorsten
1条答案
按热度按时间afdcj2ne1#
web应用程序中的嵌入式数据库需要仔细处理其生命周期。
您可以添加
javax.servlet.ServletContextListener
实施(标有@WebListener
注解或包含在web.xml
)并将显式数据库关闭添加到contextDestroyed()
方法。你可以在这里强制关闭数据库
connection.createStatement().execute("SHUTDOWN")
. 如果您的应用程序需要在卸载期间向数据库写入某些内容,则应该在该命令之前完成。如果没有显式关闭,h2会在关闭所有连接时关闭数据库,如果没有显式配置其他行为(例如jdbc url中的参数)。例如,
DB_CLOSE_DELAY
设置额外的延迟,可能应用程序使用该设置,因此h2不会立即关闭数据库,或者应用程序不会立即关闭所有连接。无论如何,当您尝试更新fly的web应用程序时,tomcat会在卸载旧版本之前尝试初始化新版本。如果h2位于web应用程序本身的类路径中,那么新版本将无法在短时间内连接到数据库,此时新版本已经联机,但旧版本尚未卸载。
如果不喜欢,可以运行独立的h2服务器进程,并在web应用程序中使用到它的远程连接。
另一个选择是将h2移动到tomcat本身的类路径,并将连接池配置为
server.xml
,在这种情况下,它不应该受到应用程序生命周期的影响。在这两种情况下,你不应该使用
SHUTDOWN
命令。更新
当客户端服务器连接到远程服务器时,这种异常意味着服务器决定关闭数据库,因为没有活动连接。此操作不能中断,并在中间恢复。在此过程中尝试打开到同一数据库的新连接时,它最多会等待1分钟,等待此过程完成后才能再次打开数据库。此超时不可配置。
有两种可能的解决办法。
DB_CLOSE_DELAY
设置可以在几秒钟内与一些较大的值一起使用。关闭所有连接后,数据库将在指定的秒数内保持联机。-1
也可用于设置无限超时。你可以试着加快关机的速度,但你必须自己弄清楚是什么花了这么多时间。默认情况下,文件压缩过程限制为200毫秒,可能需要更长的时间,但我认为应该不会那么长。可能您有很多临时对象或未提交的数据。也许你有一个非常高的数据库文件碎片。不进一步调查很难说出哪里出了问题。