mysql - Spring Boot + Liquibase:通信链接失败

标签 mysql spring-boot connection-pooling liquibase spring-jdbc

我在所有项目中都使用Liquibase,我真的很喜欢它处理数据库更新的方式,但是最近我遇到了这个问题:

liquibase                                : Successfully acquired change log lock
liquibase                                : Successfully released change log lock
liquibase                                : Could not release lock

liquibase.exception.LockException: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during rollback(). Transaction resolution unknown.
    at liquibase.lockservice.StandardLockService.releaseLock(StandardLockService.java:283) ~[liquibase-core-3.5.5.jar!/:na]
    at liquibase.Liquibase.update(Liquibase.java:218) [liquibase-core-3.5.5.jar!/:na]
    at liquibase.Liquibase.update(Liquibase.java:192) [liquibase-core-3.5.5.jar!/:na]
.
.
.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during rollback(). Transaction resolution unknown.
.
.
liquibase                                : Failed to restore the auto commit to true
.
.
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 16,913 milliseconds ago.  The last packet sent successfully to the server was 89 milliseconds ago.
.
.
Caused by: java.lang.NullPointerException: null
    at com.mysql.jdbc.MysqlIO.clearInputStream(MysqlIO.java:899) ~[mysql-connector-java-5.1.46.jar!/:5.1.46]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2477) ~[mysql-connector-java-5.1.46.jar!/:5.1.46]


我的服务器上正在运行3个应用程序。其中一个运行了大约2年。第二次运行2个月,第三个运行新的。

它们都是Spring Boot应用程序。

当我想更新第二个应用程序的jar时,这开始发生,我停止了旧的jar,运行了新的jar,但无法从上面的错误开始。
然后我运行同一应用程序的旧jar,它开始就很好。我尝试停止并重新启动这个旧的jar,有几次我得到了上面的错误,但大多数情况下它就很好了。

我尝试重新启动服务器(所有三个应用程序均作为系统启动的服务启动),但由于相同的错误,它们均未成功启动。连两年都没有。我停止了所有其他应用程序,然后使用这个持久的应用程序再试一次,直到启动它一直失败。

可能是内存问题吗?我正在使用具有1核心和2gb RAM的DigitalOcean小滴。

另外,我注意到的是,当它成功启动时,日志如下所示:

liquibase                                : Successfully acquired change log lock
liquibase                                : Reading from myDataBase.DATABASECHANGELOG
liquibase                                : Successfully released change log lock


注意在获取和释放锁之间的语句。我还怀疑在获取锁和读取变更日志之间的时间问题。但是不知道我是否可以增加时间或如何增加时间。

更新

我不知道问题的根源,但是在将liquibase-core更新到v3.7.0之后,所有应用程序都可以正确启动

更新2

关于以前的更新,我正在测试不是因为问题已得到解决,而是很少出现。但这已经发生了

重要更新3

经过一番挖掘,我意识到与此同时,该团队正在使用DB Connection Pool。 application.properties文件包含以下内容:

spring.datasource.tomcat.initial-size=5
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=5
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=5
spring.datasource.tomcat.default-auto-commit=true


遗憾的是,我对DB Pool的了解不多。但是引起我注意的是关于auto-commit的最后一行。上一次出现此错误。我禁用所有这些行,该应用程序开始正常运行。我不知道这是否只是巧合。

非常感谢你!

更新4

我回到正题...我不知道如何解决这个问题

更新5

我将mysql-connector-java更新为v8.0.15。我的服务器有MySQL v5.6.33。我仍然遇到此问题,现在无法重新启动我的应用程序。

完成上述更改后,现在异常以以下结尾:

The last packet successfully received from the server was 10,036 milliseconds ago.  The last packet sent successfully to the server was 10,036 milliseconds ago.
.
.
.
Caused by: java.io.IOException: Socket is closed
    at com.mysql.cj.protocol.AbstractSocketConnection.getMysqlInput(AbstractSocketConnection.java:72) ~[mysql-connector-java-8.0.15.jar!/:8.0.15]
    at com.mysql.cj.protocol.a.NativeProtocol.clearInputStream(NativeProtocol.java:833) ~[mysql-connector-java-8.0.15.jar!/:8.0.15]
    ... 92 common frames omitted


更新6-替代解决方案

为了清楚起见,我决定通过在liquibase.enabled=false中设置application.properties来禁用项目中的liquibase。现在,我可以随时启动/停止/重新启动应用程序了。由于我仅使用liquibase来维护数据库,并且执行了所做的更改(问题在于释放锁时),因此我将启用Liquibase只是为了更新架构,然后禁用它来运行应用程序

更新7-我想我已经解决了

我不断重复地停止和启动应用程序,每次执行该操作时,我都会得到Socket is closed,因此我开始着眼于计时问题...从引发的异常中,我注意到每次它说的内容:


  从服务器成功接收到的最后一个数据包是在xxxx毫秒之前。


在几毫秒之前,我得到的最小值是10.085,并且从不知道此问题从未出现时,我偶然就收到了同一应用的一些日志。从这些日志语句中,我可以测量获取更改日志锁和释放它之间的时间。令我惊讶的是,它只有大约9秒,而且从未超过此时间。

因此,我登录到mysql控制台并发出:

show variables LIKE '%timeout%';


这给了我一个定义的超时列表。在那里,connect_timeout是最小的,设置为10秒。一定是这样。

我用谷歌搜索了如何设置该值。我尝试创建文件/etc/my.cnf并将其添加到其中:

[mysqld]
connect_timeout=20


然后用以下命令重启mysql:

sudo /etc/init.d/mysql restart


但是,当我重新登录到mysql控制台时,该值仍为10。因此,在mysql控制台中,我发出了另一个命令:

SET GLOBAL connect_timeout=20;


并且值已更新(我不知道重启后是否还会持续)

我再次重新启动mysql,然后...!现在,这些应用程序通常在启用liquibase的情况下启动。我很高兴! :-)

最佳答案

你解决了吗?

我遇到了类似的问题,并通过强制Liquibase以同步模式执行来解决了该问题。
您的spring boot应用是否是由jhipster生成的?如果是这样,请查看DatabaseConfiguration并将其从AsyncSpringLiquibase更改为SpringLiquibase

关于mysql - Spring Boot + Liquibase:通信链接失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57154254/

相关文章:

MySQL 更新值 : How to separate 1 & -1 in query

mysql - 如何为所有浏览器存储无限量的 cookie 条目

java - 如何在到达带注释的句柄之前转换 Requestbody 的字段

mysql - JpaRepository保存值总是返回null

mysql - 如何在 Rails 中并行建立与多个数据库的连接?

mysql - 从Lua表向数据库(Mysql)插入数据

mysql - 使用条件,根据是否使用 SUM,我会得到不同的结果

spring-boot - 为什么在实体上同时使用@AllArgsConstructor 和@NoArgsConstructor?

java - Tomcat8 使用连接池到 OracleDB 的问题

mysql - ruby 、MySQL : Connection pool that is outside of the rails framework?