【问题标题】:H2 in Tomcat SqlException locked by another process when embedded mode嵌入模式时,Tomcat SqlException 中的 H2 被另一个进程锁定
【发布时间】:2014-06-17 18:39:28
【问题描述】:

我的 Web 项目在 Tomcat 7 中运行。我的服务器提供商已经有一个 MySql 服务器,但是我想使用 H2,因为它给了我更多的灵活性和速度。我的服务器提供商对我施加了一个限制,即我不应该启动一个新线程,这样做会自动导致 tomcat 停止。 我的项目处于 alpha 接近 beta 阶段,因此在本地进行了测试。我经常收到另一个进程锁定的 SqlException。当 Tomcat 更新线程池时会发生这种情况,大多数时候发生在从 Eclipse 自动发布时(这不是交易,因为它不会在服务器上发生),但有时它只是随机发生。 我的应用程序不直接访问数据库,而是通过一个我确信它不会造成问题但也可以防止它发生的包装器。 看起来 Tomcat 它正在发送保持与后台连接的线程,并且任何前台线程都会失败(我的应用程序是数据库密集型的)。 在服务器模式下打开连接将解决问题,但它将在我不大声的新进程中运行。 我想保留 H2,所以在我必须切换到 MySql 之前,我需要以下任何答案的解决方案:

  • 我能否以某种方式连接到嵌入式 H2 而不会发生 Tomcat 线程池冲突?
  • 我可以在不创建新进程的情况下连接到服务器模式 H2 吗?

注意:我不能发布任何实际代码。我确定不是我的应用程序问题。我认为没有必要,但如果需要,我会写一个关于我的包装器如何处理连接的描述,但问题已如上所述确定。

【问题讨论】:

  • 当你说不允许启动一个新线程时,它真的是一个线程还是一个进程?
  • @Serge Ballesta 对不起,如果我弄错了,但是,Java 中关于线程和进程的区别是什么?如果是这样,我将检查我的服务器提供商条件和 h2 文档并回复您
  • 我想你是不允许创建新进程的,因为 Tomcat 已经是多线程的了。
  • @Serge Ballesta 我已经与我的服务器提供商确认我不允许在服务器模式下运行 H2,它不符合我的条件。
  • 我做了一些研究和测试,H2应该允许多个连接,只要它们来自同一个JVM。您应该提供有关如何声明数据库以及正在使用的连接池的更多详细信息,但我已经怀疑 Eclipse 和 Tomcat 在同一时刻尝试连​​接数据库,这是不允许的。您能否尝试不使用 Eclipse 直接在 Tomcat 下运行您的应用程序并对其施加压力(多个连接!)以查看问题是否仍然存在。

标签: java tomcat h2


【解决方案1】:

编辑:构建-部署步骤的精度

由于我没有 Eclipse 环境,我无法完全重现您的问题。但是:

  • H2 文档清楚地表明 H2 接受多个同时连接来自同一个 JVM(参考:Feature - Multiple connections 在 h2database 文档中)
  • 相同的文档清楚地表明 H2 不接受来自多个进程的直接连接(需要一个充当服务器,另一个使用 TCP 连接) - 这不是您的问题,因为您的提供商不允许您创建其他进程,但这是您错误的原因
  • 我可以在一个具有多个连接的进程中打开 H2 数据库(以嵌入式模式)进行一些测试,并且可以处理同时请求(5 个连接,每个请求一个请求,一次读取 5 个结果集一行)
  • 我可以对同一进程的 2 个同步线程(thread1 row1、thread2 row1、thread1 row2、thread2 row2 ...)进行类似的测试
  • 一旦在另一个进程 (h2console) 中打开数据库,我就会收到错误 Database may be already in use: "Locked by another process"

所以我现在有充分的理由说问题的发生是因为 Eclipse 在编译部署过程中打开了数据库(我知道 Netbeans 可以这样做......),或者因为它有一个视图允许开发者(您)直接访问数据库(Netbeans 也可以这样做....)。如果应用程序在 Eclipse 关闭数据库之前启动,您可能会遇到竞争条件。

因为您的生产环境中没有 Eclipse(也没有任何其他进程访问数据库),所以这应该不是问题。

您可以通过这些简单的步骤来确认:

  • 在 Eclipse 下生成战争
  • 从 Eclipse 退出
  • 启动一个新的 Tomcat 实例(在您的开发机器上)
  • 在该实例下部署您的应用程序,并优先从两个不同的浏览器连接到它,以确保至少有 2 个连接

不应发生异常。

当然,如果你习惯了,你可以使用像Apache JMeter这样的工具来强调应用程序

即使Eclipse 自己不访问数据库,在部署步骤中也可能发生很多事情。摆脱这种情况的一种简单方法是在开发机器中部署新版本之前小心地停止并取消部署应用程序。如果问题不再出现,您在生产中应该没有问题(只要您遵守这些步骤)。

【讨论】:

  • 您的回答存在一些误解。 Eclipse 不访问数据库,只有我的应用程序可以。 Eclipse 所做的是将我的应用程序自动构建并自动发布到 Eclipse 处理的 Tomcat 服务器中。那时,正如我所说,持有连接的线程被后台处理并且无法通信。我想在独立的 Tomcat 中对其进行测试,但是 Ubuntu 14.4 tomcat7 包看起来已损坏或未维护,我还无法修复它。然而,主要问题是有时会在 Eclipse 不做任何事情的情况下发生。我会在提供者的服务器上做一个测试。
  • 第一部分,我现在无法访问eclipse,我稍后再试试;但是您使用的是 Hibernate 还是 JPA ;以及您的构建系统是什么(本机 eclipse、ant 或 maven 或 ...)。对于第二个,您应该至少有一个 Tomcat 实例,即 Eclipse 使用的实例。可以独立于 Eclipse 使用吗?
  • 非常感谢您的跟进。没有休眠或 JPA。没有 Maven,只有 Eclipse 构建 + 一些自定义脚本来自动生成静态内容。我还不能在我的 Ubuntu 14.4 测试机器上运行 Tomcat,因为启动失败,从存储库或独立,任何分步在线指南都适用于较旧的 Ubuntu 版本或不正确,我在 AskUbuntu 中的问题没有得到回答。但是,如果不可能,我将继续尝试在我的本地机器上进行测试或在服务器上进行测试。然后我会回复你。
  • @JuanGarcia 试图查看 Eclipse 是如何构建和部署的,但这取决于 servlet 容器的声明方式......对于 Ubuntu 上的 Tomcat(我的仍然是 12.04)我陷入了同样的陷阱和结束直接从Apache Tomcat site 下载并安装在我的主目录中。不是 Debian-Ubuntu 的方式,但它确实有效......
  • @JuanGarcia 在我的答案末尾添加一个精度。
猜你喜欢
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
相关资源
最近更新 更多