线上重启 MySQL 之后,Tomcat 下的网站连接数据库异常,用同样的用户名和密码通过终端登录数据库正常,排除用户名及密码错误。终端登录过之后,Tomcat 下的网站连接数据库恢复正常,如果再次重启 MySQL,在通过终端登录之前,Tomcat 下的网站连接数据库,又会失败。

环境

  • CentOS 7
  • MySQL 8.x
  • Tomcat 9.x

现象

MySQL 重启之后,运行在 Tomcat 下的网站连接数据库失败,重启 Tomcat 提示:java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.,同时还有以下日志:

1
2
3
4
lastAcquisitionFailureDefaultUser -> java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
...
20-07-01 16:55:20.580 WARN SqlExceptionHelper Line129 - SQL Error: 0, SQLState: null
20-07-01 16:55:20.581 ERROR SqlExceptionHelper Line131 - Connections could not be acquired from the underlying database!

原因:用户加密插件

MySQL 加密的插件方式

mysql 8.0 修改了加密的插件方式,创建用户时,如果不指定,会默认用 caching_sha2_password 加密方式,在应用程序连接 MySQL 之前,需要先以相同的用户登录一次 MySQL,应用程序才可以正常连接,一旦重启 MySQL,之前的登录缓存会失效,应用程序将不能连接 MySQL。

如果遇到在非人工操作的情况下服务器重启,那么应用程序将不能连接 MySQL,所以,这是不被允许的。除非在 Tomcat 启动脚本中添加终端登录 MySQL 的操作,但这种方式会增加部署项目的复杂度,本人没有尝试这种方式。

解决办法比较简单,只需要将 MySQL 用户密码的加密方式改为 mysql_native_password 即可,见下面的操作。

解决

将 MySQL 用户的 plugin 由 caching_sha2_password 改为 mysql_native_password,比如,我们修改 admin 的 plugin:

1
2
ALTER USER 'admin'@'localhost' IDENTIFIED WITH mysql_native_password BY 'new_password';
FLUSH PRIVILEGES;

查看用户密码加密插件方式

1
2
3
4
5
6
7
8
9
10
11
mysql> select user,host,plugin from mysql.user; 
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| admin | localhost | mysql_native_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)