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.23 mysql-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:提升预编译性能
六、验证层:连接健康检查与驱动版本确认流程
可通过以下方式双重验证修复效果:
- 应用启动后查看日志中 JDBC 驱动加载信息:
Loaded class 'com.mysql.cj.jdbc.Driver'(注意cj表示 Connector/J 8.x) - 运行 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+
其共性解法始终是:**识别协议断裂点 → 升级客户端驱动 → 校验握手流程 → 固化版本治理**。
```本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报