Docker MySQL 在超时后删除表:连接关闭后不允许操作

问题描述

一个非常奇怪的情况。我正在将 Spring Boot 与在 docker 容器中运行的 Spring Data JPA 和 MysqL 一起使用。启动应用程序后一切正常(数据库在启动时使用 spring.jpa.hibernate.ddl-auto=create-drop 进行初始化)。

如果我让应用保持运行状态,大约 10 分钟后,在运行另一个请求时,我会返回 table doesn't exist检查数据库,我可以看到所有的表都没有了(架构还在)!

日志在错误发生前向我显示此警告:

2020-12-20 16:15:41.151  WARN 11018 --- [nio-8080-exec-4] com.zaxxer.hikari.pool.PoolBase          : myDS - Failed to validate connection com.MysqL.cj.jdbc.ConnectionImpl@67dd33b2 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2020-12-20 16:15:41.153  WARN 11018 --- [nio-8080-exec-4] com.zaxxer.hikari.pool.PoolBase          : myDS - Failed to validate connection com.MysqL.cj.jdbc.ConnectionImpl@3817c06d (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2020-12-20 16:15:41.155  WARN 11018 --- [nio-8080-exec-4] com.zaxxer.hikari.pool.PoolBase          : myDS - Failed to validate connection com.MysqL.cj.jdbc.ConnectionImpl@536cd1b2 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

然后:

2020-12-20 16:15:41.161  WARN 11018 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.sqlExceptionHelper   : sql Error: 1146,sqlState: 42S02
2020-12-20 16:15:41.161 ERROR 11018 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.sqlExceptionHelper   : Table 'tasker.account' doesn't exist
2020-12-20 16:15:41.173  INFO 11018 --- [nio-8080-exec-4] o.h.e.internal.DefaultLoadEventListener  : HHH000327: Error performing load command

我还在 application.properties 中添加了此设置:

spring.datasource.hikari.max-lifetime=600000 匹配 MysqL 的设置。

Docker 开始于:

docker run --name=MysqL1 --restart on-failure -d MysqL/MysqL-server:8.0

注意:MysqL 的本地实例永远不会发生这种情况(本机,不在 docker 中)

任何帮助将不胜感激。

解决方法

create-drop 将在关闭 SessionFactory 时删除 schema,现在让我们来处理 SessionFactory 关闭的部分,它可能与网络连接超时有关,导致 SessionFactory 被 springboot 自动关闭。

您可以向 application.properties 添加心跳以防止发生这种行为,无论如何这部分已经解决了我的生产环境中的许多问题,因此添加这一点非常有帮助:

#HeartBeat the database so that connections don't die otherwise the connections die silently
#and when a query commes along the JPA will throw an error and keep throwing errors and a restart of the process
#is inevitable
spring.datasource.testWhileIdle=true
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery=SELECT 1

我将在此处提供有关检查连接和池健康状况的答案的链接 Connection to Db dies after >4<24 in spring-boot jpa hibernate

另一件事,因为这只是一个开发环境,您可以将 create-drop 更改为 create,这将配置 springboot 以删除现有架构并在 springboot 应用程序启动时以这种方式创建一个新架构连接丢失时永远不会被破坏。

,

看看这个答案:

How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?

当您使用 create-drop 时,您可能对他回答的以下部分感兴趣:

通常在测试用例场景中,您可能会使用 create-drop 所以 你创建了你的模式,你的测试用例添加了一些模拟数据,你 运行您的测试,然后在测试用例清理期间,架构 对象被删除,留下一个空的数据库。

,

问题似乎出在此设置中:

spring.datasource.hikari.max-lifetime

在 application.properties 中添加此设置似乎解决了问题:spring.datasource.hikari.max-lifetime=100000 而与 mySQL 值完全匹配的 spring.datasource.hikari.max-lifetime=600000 不起作用 - 即导致表被删除。