友链提交
请认真填写以下信息,谢谢!

博客信息

(请填写完整的网址,例如:https://www.example.com)
(贵站展示本站链接的页面地址,一般是友链页面,填写后将自动验证友链关系有效性)
(用于抓取文章)
(用于接收通知)

连接MySQL报错解决

  1. 首页
  2. 学习记录
  3. 连接MySQL报错解决

问题背景

最近在使用 JDBC 连接 MySQL 数据库时遇到了一个报错:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException。经过一番排查,发现问题出在 MySQL 驱动版本和数据库版本不匹配上。

今天就把完整的排查过程和解决方案分享给大家,希望能帮助到遇到同样问题的朋友。

问题描述

我使用的代码如下:

public class Conn {

    final String DB_URL = "jdbc:mysql://localhost:3306/message";
    final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    final String USER = "root";
    final String PASS = "password";

    public Connection cn = null;
    public PreparedStatement pr = null;
    public ResultSet rs = null;

    public Conn() {
        try {
            Class.forName(JDBC_DRIVER);
            cn = DriverManager.getConnection(DB_URL, USER, PASS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            if (cn != null) cn.close();
            if (pr != null) pr.close();
            if (rs != null) rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行后出现了连接错误。

问题原因分析

经过检查后发现,我连接的 MySQL 数据库是 8.0 版本,而项目中使用的 com.mysql.jdbc.Driver 驱动包是 5.1 版本

这就是问题所在:驱动版本太老了,不支持 MySQL 8.0 的新特性。

第一个错误:驱动类过时

于是我将 com.mysql.jdbc.Driver 的版本改为 8.0.11,重新执行代码后,出现了新的警告:

Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'.
The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

警告信息解读:

  • com.mysql.jdbc.Driver 已经被弃用
  • 新的驱动类是 com.mysql.cj.jdbc.Driver
  • 驱动会通过 SPI 自动注册,通常不需要手动加载

第二个错误:SSL 连接警告

继续执行后,又出现了 SSL 相关的警告:

Thu May 28 10:34:56 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended.
According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set.
For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'.
You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

警告信息解读:

  • 不建议在没有服务器身份验证的情况下建立 SSL 连接
  • 根据 MySQL 5.5.45+、5.6.26+ 和 5.7.6+ 的要求,默认情况下必须建立 SSL 连接
  • 我们需要通过设置 useSSL=false 显式地禁用 SSL
  • 或者设置 useSSL=true 并为服务器证书验证提供信任存储

第三个错误:时区问题

修改后继续执行,又出现了一个新错误:

Exception in thread "main" java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

错误信息解读:

  • 这是一个时区问题
  • 数据库安装时默认为英语,0:00 时区
  • Windows 系统中,XP 的时区是 GMT,而 Win7 的时区是 UTC
  • MySQL 返回的时间会比实际时间要早 8 小时
  • 提示很明确:可以通过配置服务器或通过 serverTimeZone 配置 JDBC driver 连接参数来指定一个特定的时区

解决方案

方案一:配置 JDBC 连接参数(推荐)

在 URL 连接字符串后面加上参数:?useSSL=false&serverTimezone=UTC

修改后的代码:

public class Conn {

    final String DB_URL = "jdbc:mysql://localhost:3306/message?useSSL=false&serverTimezone=UTC";
    final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    final String USER = "root";
    final String PASS = "password";

    public Connection cn = null;
    public PreparedStatement pr = null;
    public ResultSet rs = null;

    public Conn() {
        try {
            Class.forName(JDBC_DRIVER);
            cn = DriverManager.getConnection(DB_URL, USER, PASS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            if (cn != null) cn.close();
            if (pr != null) pr.close();
            if (rs != null) rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案二:修改 MySQL 数据库配置

如果你不想每次配置 JDBC 参数都使用 serverTimezone=UTC 来进行连接,也可以直接修改 MySQL 数据库的时区配置。

查看当前时区设置:

show variables like '%time_zone%';

输出示例:

+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+

设置为东八区(北京时间):

set global time_zone='+8:00';

执行结果:

Query OK, 0 rows affected (0.00 sec)

验证修改:

重新打开命令行,进入 MySQL,查询时区:

show variables like "%time_zone%";

输出结果:

+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set, 1 warning (0.01 sec)

此时,即使 JDBC 不加 serverTimezone=UTC,仍然可以正确连接。

常用时区参数

在 JDBC URL 中,可以使用以下时区值:

时区值 说明
UTC 协调世界时
GMT 格林尼治标准时间
GMT%2B8:00 东八区(北京时间,URL 编码的 GMT+8:00
Asia/Shanghai 上海时区
Asia/Hong_Kong 香港时区
Asia/Taipei 台北时区

推荐使用:

  • 国际化应用:serverTimezone=UTC
  • 国内应用:serverTimezone=Asia/ShanghaiserverTimezone=GMT%2B8:00

常见问题

Q1:useSSL=true 和 useSSL=false 有什么区别?

  • useSSL=true:使用加密连接,更安全,但需要配置证书
  • useSSL=false:不使用加密连接,适合开发环境

Q2:为什么会出现乱码?

时区错误信息中出现的 'Öйú±ê׼ʱ¼ä' 是乱码,原文应该是"中国标准时间"。这是因为字符编码问题导致的。

解决方法:

  • 在 JDBC URL 中添加字符编码参数:?characterEncoding=utf8

完整的 URL 示例:

jdbc:mysql://localhost:3306/message?useSSL=false&serverTimezone=UTC&characterEncoding=utf8

Q3:时区设置会影响什么?

时区设置主要影响:

  • TIMESTAMP 类型的字段
  • NOW()CURRENT_TIMESTAMP 等函数
  • 时间戳的读取和写入

希望这篇记录能帮助到遇到同样问题的朋友!如果你有其他问题或更好的解决方案,欢迎在评论区交流。


用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

浮生闲记

intj 建筑师

站长

具有版权性

请您在转载、复制时注明本文 作者、链接及内容来源信息。 若涉及转载第三方内容,还需一同注明。

具有时效性

目录

欢迎来到浮生闲记的站点,为您导航全站动态

41 文章数
2 分类数
32 评论数
46标签数