【发布时间】:2016-03-08 15:13:41
【问题描述】:
在多线程环境中使用 H2 数据库时出现 Stackoverflow 错误
我们的应用程序具有查询 H2 数据库和检索结果集的服务层。
服务层使用开源集群中间件“Sequoia”(提供负载平衡和 透明故障转移)并且还管理数据库连接。
https://sourceforge.net/projects/sequoiadb/
我们的服务层有 50 个服务方法,我们将服务方法公开为 EJB 的 .在调用 EJB 时 我们从服务(包括 H2 READ)获得平均响应时间为 0.2 秒的响应。
DAO 层,使用 Hibernate Criteria 查询数据库,我们也使用 JPA2.0 实体管理器来管理数据源。
对于负载测试,我们创建了一个调用所有 50 个 EJB 方法的测试类(带有一个 main 方法)。
创建了 50 个线程,所有线程都调用了测试类。首次运行执行正常,所有 50 个线程均已成功完成 调用 50 个 EJB 方法。
当我们再次触发测试类时,我们遇到了“stackoverflowerror”。详细的stacktrace如下所示
org.h2.jdbc.JdbcSQLException: General error: "java.lang.StackOverflowError" [50000-176]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:344)
at org.h2.message.DbException.get(DbException.java:167)
at org.h2.message.DbException.convert(DbException.java:290)
at org.h2.server.TcpServerThread.sendError(TcpServerThread.java:222)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:155)
at java.lang.Thread.run(Thread.java:784)
Caused by: java.lang.StackOverflowError
at java.lang.Character.digit(Character.java:4505)
at java.lang.Integer.parseInt(Integer.java:458)
at java.lang.Integer.parseInt(Integer.java:510)
at java.text.MessageFormat.makeFormat(MessageFormat.java:1348)
at java.text.MessageFormat.applyPattern(MessageFormat.java:469)
at java.text.MessageFormat.<init>(MessageFormat.java:361)
at java.text.MessageFormat.format(MessageFormat.java:822)
at org.h2.message.DbException.translate(DbException.java:92)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:343)
at org.h2.message.DbException.get(DbException.java:167)
at org.h2.message.DbException.convert(DbException.java:290)
at org.h2.command.Command.executeUpdate(Command.java:262)
at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:199)
at org.h2.server.TcpServer.addConnection(TcpServer.java:140)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:152)
... 1 more
at org.h2.engine.SessionRemote.done(SessionRemote.java:606)
at org.h2.engine.SessionRemote.initTransfer(SessionRemote.java:129)
at org.h2.engine.SessionRemote.connectServer(SessionRemote.java:430)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:311)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:107)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:91)
at org.h2.Driver.connect(Driver.java:74)
at org.continuent.sequoia.controller.connection.DriverManager.getConnectionForDriver(DriverManager.java:266)
然后我们甚至在 EJB Invocation 之间添加了一个随机线程休眠(10-25 秒)。执行成功三次(全部 50 个 EJB 调用) 当我们第 4 次触发时,它因上述错误而失败。
即使线程数为 25,我们也会看到上述失败。
失败是随机的,似乎没有模式。如果我们遗漏了任何配置,请告诉我们。
如果您需要任何其他信息,请告诉我。提前感谢您的帮助。
技术栈:
1) Java 1.6
2) h2-1.3.176
3) 管理数据库连接打开和关闭的 Sequoia 中间件。
-Variable Connection Pool Manager
-init pool size 250
【问题讨论】: