影评周公子 2026-04-07 10:25 采纳率: 99%
浏览 0
已采纳

MyBatis连接MySQL 8报错“Unknown system variable 'query_cache_size'”如何解决?

MyBatis连接MySQL 8时出现“Unknown system variable 'query_cache_size'”错误,根本原因是:MySQL 8.0已**彻底移除查询缓存(Query Cache)相关系统变量**(如`query_cache_size`、`query_cache_type`),而旧版MySQL JDBC驱动(如5.x系列)在初始化连接时仍尝试读取这些已被废弃的变量,导致握手失败。常见于使用`mysql-connector-java:5.1.x`连接MySQL 8+的场景。解决方案明确且唯一:**升级JDBC驱动至8.0及以上版本**(如`8.0.33`或`8.2.x`),并确保`pom.xml`中排除旧驱动依赖,避免传递性冲突。同时建议在连接URL中添加`allowPublicKeyRetrieval=true&useSSL=false`(开发环境)及`serverTimezone=UTC`等兼容参数。无需修改MyBatis配置或MySQL服务端——该问题纯属客户端驱动兼容性问题。
  • 写回答

1条回答 默认 最新

  • fafa阿花 2026-04-07 10:25
    关注
    ```html

    一、现象层:典型错误日志与触发场景

    开发中常见报错如下:

    Caused by: java.sql.SQLException: Unknown system variable 'query_cache_size'
    	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
    	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3978)
    	...(堆栈省略)

    该异常在应用启动时 MyBatis 初始化 SqlSessionFactory 阶段高频出现,尤其集中于 Spring Boot 2.3–2.7 + MySQL 8.0.28+ 环境。本质是 JDBC 驱动与服务端协议握手失败,非 SQL 语法错误,亦非 MyBatis 映射配置问题

    二、机制层:MySQL 8.0 查询缓存的彻底移除与驱动兼容性断层

    MySQL 官方自 8.0.3 版本起正式删除查询缓存子系统,包括:

    • query_cache_size(缓存内存上限)
    • query_cache_type(启用开关)
    • query_cache_limit 等全部相关变量

    mysql-connector-java:5.1.x(如 5.1.49)仍沿用 MySQL 5.7 协议逻辑,在连接初始化阶段主动执行 SELECT @@query_cache_size 等系统变量查询——服务端返回 ER_UNKNOWN_SYSTEM_VARIABLE 错误码,驱动无法降级处理,直接抛出 SQLException

    三、诊断层:依赖树穿透与冲突定位(含 Maven 分析)

    使用以下命令可快速识别隐式引入的旧驱动:

    mvn dependency:tree | grep mysql

    常见污染路径示例:

    依赖来源引入版本是否冲突
    spring-boot-starter-jdbc (2.5.x)mysql:mysql-connector-java:5.1.49✅ 是(传递依赖)
    druid-spring-boot-starter:1.1.23mysql-connector-java:5.1.47✅ 是
    显式声明 mysql-connector-java:8.0.33❌ 否(需确保优先级最高)

    四、解决层:精准升级与防御性配置(含完整 pom.xml 片段)

    核心操作为强制统一驱动版本 + 排除所有 5.x 传递依赖

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.2.0</version>
      <scope>runtime</scope>
    </dependency>
    
    <!-- 排除 Spring Boot 2.5.x 自带的 5.1.x -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
      <exclusions>
        <exclusion>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    五、增强层:JDBC URL 兼容参数最佳实践

    MySQL 8+ 连接字符串需补充关键参数以规避次生问题:

    • serverTimezone=UTC:避免 timestamp 转换时区异常
    • allowPublicKeyRetrieval=true:解决 RSA 密钥交换失败(开发环境)
    • useSSL=false:禁用 SSL(仅限开发;生产应配 TLS)
    • cachePrepStmts=true&useServerPrepStmts=true:提升预编译性能

    六、验证层:连接健康检查与驱动版本确认流程

    可通过以下方式双重验证修复效果:

    1. 应用启动后查看日志中 JDBC 驱动加载信息:Loaded class 'com.mysql.cj.jdbc.Driver'(注意 cj 表示 Connector/J 8.x)
    2. 运行 SQL:SELECT VERSION(), @@protocol_version; 确认服务端为 8.x 且协议版本 ≥ 10

    七、演进层:MyBatis 与 MySQL 生态协同演进图谱

    下图展示关键组件版本对齐关系(Mermaid 流程图):

    graph LR A[MySQL 5.7] -->|支持 query_cache_*| B[mysql-connector-java 5.1.x] C[MySQL 8.0.3+] -->|移除 query_cache_*| D[mysql-connector-java 8.0+] D --> E[MyBatis 3.4.6+] E --> F[Spring Boot 2.4+ 默认适配] style A fill:#f9f,stroke:#333 style C fill:#9f9,stroke:#333 style D fill:#6af,stroke:#333

    八、避坑层:被广泛误用的“伪解决方案”清单

    以下操作完全无效甚至有害,务必避免:

    • 修改 MySQL 配置文件添加 query_cache_size = 0(8.0 不识别该参数)
    • 在 MyBatis 的 mybatis-config.xml 中配置缓存开关(与 JDBC 握手无关)
    • 降级 MySQL 至 5.7(违背技术演进,丧失 JSON/CTE/原子 DDL 等核心能力)
    • 手动 patch JDBC 驱动源码(破坏可维护性与安全更新)

    九、架构层:面向未来的驱动治理策略

    建议在企业级项目中建立JDBC 驱动白名单管控机制

    • 通过 Maven Enforcer Plugin 强制约束 mysql-connector-java 版本范围:[8.0.33,)
    • CI/CD 流水线中加入 mvn verify -Denforcer.fail=true 自动拦截违规依赖
    • 构建内部 starter(如 company-mysql8-starter),预置全量兼容参数与排除规则

    十、延伸层:同类兼容性问题模式泛化(举一反三)

    此问题属于典型的“服务端激进废弃 + 客户端惰性兼容”范式,类似案例包括:

    • PostgreSQL 15 移除 password_encryption → pgjdbc 42.6+ 才兼容
    • Oracle 21c 废弃 ojdbc7 → 必须升级至 ojdbc11
    • SQL Server 2022 默认禁用 TLS 1.0/1.1 → mssql-jdbc 10.2+ 强制 TLS 1.2+

    其共性解法始终是:**识别协议断裂点 → 升级客户端驱动 → 校验握手流程 → 固化版本治理**。

    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 4月8日
  • 创建了问题 4月7日