type
status
date
slug
summary
tags
category
icon
password
js
在使用 Spring Boot + Druid + SQL Server 的项目中,很多开发者会遇到如下错误:
这个错误虽然不常见,但一旦出现就很顽固,可能频繁触发甚至导致业务异常。本文将从原理出发,分析这个错误的根本原因,并提供完整的解决方案,包括日志配置,适用于 Spring Boot 3.4.4 + Druid + 多数据源(如 dynamic-datasource)。
❓ 错误来源解析
这个错误是 SQL Server 抛出的,意思是:
某个连接尝试执行已失效的 PreparedStatement(即“预定义语句”),但其对应的句柄在服务端已被释放。
产生原因:
- Druid 启用了
poolPreparedStatements
缓存机制
- 连接被复用时,继续使用旧的 PreparedStatement 句柄(已失效)
- SQL Server 会主动清除某些预编译语句(尤其是在连接空闲/复用时)
✅ 正确做法:关闭 Druid 的 PreparedStatement 缓存
在使用 SQL Server 的数据源中,必须关闭以下两个参数:
⚠️ 注意:只设置 max-pool-prepared-statement-per-connection-size=20 也会自动触发缓存启用!
✅ 多数据源场景下的完整配置示例
以下为典型的 MySQL + SQL Server 混合场景配置(基于
.properties
文件):✅ 日志输出配置(logback-spring.xml)
为了更方便地定位问题,我们建议在 Spring Boot 中使用
logback-spring.xml
来开启 Druid、MyBatis、动态数据源的调试日志。📄 src/main/resources/logback-spring.xml
内容:
✅ 请移除 application.properties 中的 logging.level.xxx 配置,避免冲突。
🧪 启动后预期日志输出
- 数据源初始化信息:
实际操作中,我的控制台没有打印这些信息,但是可以通过druid页面查看到确实关闭了
- 数据源切换日志:
- SQL 执行日志(带慢 SQL 时间):
✅ 补充建议
场景 | 建议 |
生产环境 | 日志级别建议调低至 INFO,仅打印慢 SQL |
SQL Server 数据源 | 避免使用 Druid 缓存机制,或切换为 HikariCP |
Druid 慢 SQL 日志 | 使用 filters=stat + slowSqlMillis=500 输出慢 SQL |
MyBatis SQL 日志 | 配合 logback 打印执行语句,便于调优 |
📌 依赖版本参考
- Spring Boot:3.4.4
- Druid:1.2.20+
- SQL Server JDBC Driver:
com.microsoft.sqlserver:mssql-jdbc:12.6.1.jre11
- Dynamic Datasource Starter:3.4.4
- MyBatis Plus:3.5+
✅ 总结
问题 | 原因 | 正确做法 |
找不到预定义语句句柄 | SQL Server 回收已缓存的句柄 | 关闭 Druid 的 PreparedStatement 缓存 |
日志无输出 | 默认配置不打印 Druid 日志 | 使用 logback-spring.xml 显式开启日志 |
SQL 不可见 | 没有启用 stat filter | 添加 filters=stat 与日志配合使用 |
有任何配置问题或 Spring Boot 项目调优相关问题,欢迎留言交流 👍
- 作者:吕行者
- 链接:https://www.lvy.life/article/2025/07/11/22d1f2f0-5182-8040-9dae-fc7f656c98f2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。