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。