H2 数据库,进程死锁导致访问异常的问题

来源:互联网 发布:素描教学软件下载 编辑:程序博客网 时间:2024/06/07 23:42

问题现象:

H2数据库启动后,Web Server运行正常,能通过9090端口访问,但无法访问数据库。

问题复现:

通过启动脚本重启H2数据库,复现的概率非常高(测试人员反应运行中的H2数据库也会出现连接异常的问题,该场景暂时未复现)。

问题分析:

初步断定是进程死锁导致。根据程序的堆栈信息,也支持这一判断。

对造成死锁的原因进行分析:

1 H2服务器有多种启动方式,我们使用的是Console模式,且全部使用默认参数;这种场景下,H2会按顺序逐次启动WebServer,TcpServer,PgServer。

WebServer能支持用户通过浏览器访问数据库,TcpServer支持Java程序中通过api访问数据库,PgServer支持通过PgAdmin客户端访问数据库。

2 WebServer启动后,会有一个自我检测的环节,也就是创建一个Socket去连接WebServer,来检测WebServer是否已启动;因此,WebServer的第一个
WebThread线程,就是用来处理这个自检请求的,由于自检请求没有携带正常的启动信息,因此会引发异常,进而去执行DbException.traceThowable()函数。

3 与此同时,Main函数会继续启动TcpServer,过程中会加载org.h2.Driver类;如果此时WebThead线程也恰好正在执行Driver的初始化,就会导致
死锁;如果此时WebThread线程已经执行结束并正常退出,那么Main函数就可以正常的启动TcpServer。

这也就可以解释为什么启动失败是偶发事件。

解决方案:

Console模式的启动顺序是:WebServer->OpenBrowser->TcpServer->PgServer;我们的使用场景中,其实不需要启动浏览器和PgServer;另外,WebServer在TcpServer
之前启动,会偶发启动失败的问题,应该是H2的一个bug。
H2同时提供了另一种启动模式——Server模式,该模式中各服务器的启动顺序是:TcpServer->PgServer->WebServer->OpenBrowser;

因此可以通过Server模式来启动,来避免启动失败的问题。
java -cp $H2HOME/h2-1.4.192.jar org.h2.tools.Server -web -webPort 9090 -webAllowOthers -tcp -tcpPort 9092 –tcpAllowOthers

阅读全文
0 0