StackTraces

SQL 日志不打印:先定段落,再进分支

SQL 日志要经过四道关才能到你眼前:配置活进 Environment、logger 级别放行、持久层框架把 SQL 交给日志系统、appender 和采集链路送到你的观察口。任何一道关卡住,现象都是「不打印」。先确认持久层是 JPA 还是 MyBatis、跑的是 Boot 2 还是 3,再按现象对号进分支。

排查全景图
全景导航 · 4 阶段 × 13 条分支,先在图上定位现象,再进下方路径

按首个可操作的异常分流

SQL 日志不是开了就有:配置要先活进 Environment,级别要放行,框架要把 SQL 交给日志系统,最后 appender 和采集链路要把日志送到你眼前。先确认两件事:持久层是 JPA 还是 MyBatis、跑的是 Boot 2 还是 3。再按现象对号进分支。

13 条路径 →
01 · 环境

当前环境

先记录配置写在哪个文件、哪一层缩进,以及打包产物里到底有没有这份配置。配置写错位置是最常见的哑火原因。

  • 列出项目里所有配置文件:application.yml / application.properties / 各 profile 文件
  • 确认构建产物(target/classes 或 jar 内 BOOT-INF/classes)里实际打包了哪几份
02 · 签名

报错识别

现象 / SYMPTOM
控制台与日志文件里都没有 Hibernate: select ...
也没有 DEBUG org.hibernate.SQL 行
典型写错 / COMMON MISTAKES
# 错:show-sql 写进了 datasource 命名空间
spring:
  datasource:
    show-sql: true
 
# 错:yml 缩进错位,show-sql 挂到了 logging 下
logging:
  level:
    org.hibernate.SQL: DEBUG
  show-sql: true
  • /actuator/env 里查不到 spring.jpa.show-sql → 配置根本没绑定,查键的位置、拼写和文件是否被打包
  • env 里值是 false → 配置绑上了但被别的配置源盖掉,走 A3 分支
  • 键值都对、就是没输出 → 不是配置问题,去 C1 看输出是不是走到了 stdout

spring.jpa.show_sql(下划线)靠 relaxed binding 也能绑上,别把它当反例;真正坑的是命名空间和缩进。

03 · 安全操作

快速解法

按序执行三条判据命令,用输出定位是「没绑上」还是「被打包漏了」。需要暴露 actuator 的 env 端点:management.endpoints.web.exposure.include=env。

判据一:查生效值与来源。property 不存在 → 配置没绑上;value=false → 被覆盖(去 A3)

curl -s localhost:8080/actuator/env/spring.jpa.show-sql | jq

判据二:查打包产物。grep 无输出 → 文件没被打包,查 resources 目录与多模块结构

unzip -p target/app.jar BOOT-INF/classes/application.yml | grep -n "show-sql"

修复:把键放回 spring.jpa 命名空间

spring:
  jpa:
    show-sql: true
show-sql 只是开发期开关,输出走 stdout 不进日志框架;想进日志体系请看 C1 的改法。
04 · 确认

验证

  1. 重启后 /actuator/env/spring.jpa.show-sql 返回 true,origin 指向预期配置文件
  2. 执行一次查询,控制台出现 Hibernate: select ... 输出
05 · 继续诊断

解法无效时

  1. 没有 actuator:用命令行参数 --spring.jpa.show-sql=true 启动一次,能打印就说明开关有效、问题在配置文件
  2. 仍无输出:确认用的是 JPA/Hibernate 而不是 MyBatis,MyBatis 不认这个键,去 A4
06 · 相邻原因

相关

  • A2:配置写在不激活的 profile 文件里,同样查不到生效值
  • A3:值被配置中心或环境变量覆盖
  • C1:show-sql 生效了但输出在 stdout,日志文件里照样没有

常见问题

spring.jpa.show-sql=true 配了,但一条 SQL 都没输出?
先分清是「没绑上」还是「被打包漏了」。暴露 actuator 的 env 端点,即 management.endpoints.web.exposure.include=env,再按序执行判据命令,看生效配置里到底有没有这个键,然后对症处理。
写在 application-dev.yml 里的 SQL 日志开关不生效?
那份 profile 根本没被激活。先确认线上实际激活的是哪个 profile,再决定是切换 profile,还是把配置挪到真正生效的那份文件里。
本地能打 SQL、线上不行,配置被谁改掉了?
开关被更高优先级的配置源覆盖了,例如环境变量、启动参数或配置中心。先用 env 端点定位这个键到底来自哪个源,再改对应的源,而不是反复改 application.yml。
MyBatis 配了 mybatis.configuration.log-impl 还是不打 SQL?
配置前缀和实际使用的 starter 不匹配。先确认用的是哪个 starter,再把键前缀对齐到它认的那一套,配错前缀时配置会被静默忽略。
日志里出现 SLF4J: Class path contains multiple SLF4J bindings?
classpath 上有多个 slf4j 实现互相冲突,最后绑定到哪个并不确定。用 dependency:tree 找出多余的实现并排除,目标只有一个:classpath 上只剩一个 slf4j 实现。
写了 logback-spring.xml,但完全不生效?
先核两条判据:文件在不在最终产物里、名字对不对。Spring Boot 只认约定文件名,而且打包后要能从 classpath 根目录读到,确认这两点之后再看文件内容。
org.hibernate.SQL 配成 DEBUG 了,输出还是没有?
logger 级别在上游被压死了。用 actuator 的 loggers 端点查当前生效级别,需要先暴露 management.endpoints.web.exposure.include=loggers,再决定临时改还是永久改配置。
IDE 里能看到 Hibernate: select ...,服务器日志文件里却没有?
show-sql 把 SQL 输出到了 stdout,没进日志框架,所以日志文件里抓不到。根治办法是弃用 show-sql,改用 logger 输出,例如 org.hibernate.SQL=DEBUG,让 SQL 进入日志体系。
升级到 Boot 3 之后参数绑定日志消失了?
Boot 3 换了 Hibernate 版本,绑定参数用的 logger 名也随之变了。先确认 Hibernate 版本,再选对应的 logger 名开启参数值输出,不要继续沿用 Boot 2 的写法。
MyBatis 执行了 SQL,但日志里什么都没有?
属于 log-impl 选型或级别问题。推荐组合是 log-impl 设为 Slf4jImpl,再把 mapper 包级别开到 DEBUG,这样 SQL 就进了统一日志体系,能被 appender 正常采集。
用 JdbcTemplate 或想兜底抓所有 SQL,开哪个 logger 都没用?
因为 JDBC 层本身不打日志。按连接池选型走对应路径:Druid 改配置即可开启 SQL 统计与日志,用代理方案则要动依赖。选一条路走通,别两边都开。
kubectl logs 里明明有 SQL,日志平台和文件里就是没有?
SQL 被 show-sql 打到了 stdout,而部署环境没采集 stdout。两个方向:根治是把 SQL 接入日志框架,补短板是让采集器把 stdout 一并收进去。
控制台能看到 DEBUG SQL,日志文件里却没有?
是 appender 上的过滤器把 DEBUG 挡在了门外,比如阈值被设成了 INFO 或更高。先找到这个过滤器,再决定整体放行,还是给 SQL 单独开一个专用 appender。