Docker MySQL在超时后丢弃表:连接关闭后不允许操作
Posted
技术标签:
【中文标题】Docker MySQL在超时后丢弃表:连接关闭后不允许操作【英文标题】:Docker MySQL drops tables after timeout: No operations allowed after connection closed 【发布时间】:2021-03-30 14:03:26 【问题描述】:一个非常奇怪的情况。我正在使用 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 中)
任何帮助将不胜感激。
【问题讨论】:
添加此设置似乎已经解决了问题:spring.datasource.hikari.max-lifetime=100000
而与 mySQL 值完全匹配的spring.datasource.hikari.max-lifetime=600000
不起作用。因此它是这个问题和create-drop的结合。
你的连接类型是什么?
@Perimosh 连接类型?不知道你到底是什么意思,但它是 jdbc url:spring.datasource.url=jdbc:mysql://172.17.0.2:3306/tasker?useUnicode=yes&characterEncoding=UTF-8
是嵌入的吗?如果是,是 hsqldb、h2 还是 derby?
@Perimosh 它是mysql
在 docker 上运行,如问题中所述。它不是 hsqldb、h2 或 derby。
【参考方案1】:
问题似乎出在这个设置中:
spring.datasource.hikari.max-lifetime
在 application.properties 中添加此设置似乎解决了问题:spring.datasource.hikari.max-lifetime=100000
而与 mySQL 值完全匹配的spring.datasource.hikari.max-lifetime=600000
不起作用 - 即导致表被删除。
【讨论】:
【参考方案2】: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 应用程序启动时创建一个新架构,这样架构将永远不会被破坏当连接丢失时。
【讨论】:
【参考方案3】:看看这个答案:
How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?
当您使用create-drop
时,您可能对他回答的以下部分感兴趣:
通常在测试用例场景中,您可能会使用
create-drop
所以 你创建你的模式,你的测试用例添加了一些模拟数据,你 运行你的测试,然后在测试用例清理期间,模式 对象被删除,留下一个空数据库。
【讨论】:
谢谢,但这并不能回答为什么应用程序仍在运行并且数据库在 10 分钟超时后被删除的问题。我使用create-drop
在本地以开发模式运行应用程序,它不是任何自动化测试的一部分。我启动应用程序,它超时,数据消失,但应用程序继续运行
create-drop
的值被传递给 Hibernate,其理解如下:“数据库模式将被删除并随后创建。关闭 SessionFactory 后,数据库模式将被删除。” - 我会说你的 SessionFactory 会在一段时间后关闭。你能在那里设置一个断点,看看是否会发生这种情况?
又一页试图解释spring.jpa.hibernate.ddl-auto=create-drop
的使用,显示表在SessionFactory#close()
被删除:javausecase.com/2017/09/03/hibernate-5-hbm2ddl-auto-explained
你也可以看看这个:dev.mysql.com/doc/refman/5.7/en/…
请注意,保留旧的超时值并仅将create-drop
更改为create
并不能解决问题。同样的情况 - 表被删除以上是关于Docker MySQL在超时后丢弃表:连接关闭后不允许操作的主要内容,如果未能解决你的问题,请参考以下文章
用jdbc连接mysql数据库,执行程序一段时间后控制台报连接超时。why,如何解决!