每次設定 Spring 事務日誌都要重新查詢,這篇整理各種 logging 框架的設定方式,以及如何解讀事務日誌輸出。
為何需要監控 Spring 事務日誌?
@Transactional 讓 Spring 自動管理資料庫交易,但有時候:
- 懷疑事務沒有正常開啟(方法是否真的在事務中執行?)
- 排查 N+1 問題或異常回滾(rollback)
- 確認事務傳播行為(Propagation)是否如預期
透過設定日誌層級為 TRACE,可以看到 Spring 如何開啟、提交、回滾事務。
log4j.properties 設定
1
2
3
4
5
|
# 顯示事務攔截器詳細資訊(開啟/提交/回滾)
log4j.logger.org.springframework.transaction.interceptor=TRACE
# 顯示 JDBC 事務管理器的底層操作
log4j.logger.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
|
log4j2.xml 設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<Configuration>
<Loggers>
<!-- Spring 事務攔截器 -->
<Logger name="org.springframework.transaction.interceptor"
level="TRACE" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<!-- DataSource 事務管理器 -->
<Logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager"
level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>
|
SLF4J + Logback 設定(logback.xml)
1
2
3
4
5
6
7
8
9
|
<configuration>
<!-- Spring 事務攔截器 -->
<logger name="org.springframework.transaction.interceptor"
level="TRACE"/>
<!-- DataSource 事務管理器 -->
<logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager"
level="DEBUG"/>
</configuration>
|
解讀事務日誌輸出
設定完成後,執行含有 @Transactional 的方法,會看到類似以下的日誌:
1
2
3
4
5
6
7
|
TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [com.example.service.UserService.createUser]
DEBUG o.s.j.d.DataSourceTransactionManager - Creating new transaction with name [com.example.service.UserService.createUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG o.s.j.d.DataSourceTransactionManager - Acquired Connection [xxx] for JDBC transaction
DEBUG o.s.j.d.DataSourceTransactionManager - Switching JDBC Connection [xxx] to manual commit
TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [com.example.service.UserService.createUser]
DEBUG o.s.j.d.DataSourceTransactionManager - Committing JDBC transaction on Connection [xxx]
DEBUG o.s.j.d.DataSourceTransactionManager - Releasing JDBC Connection [xxx] after transaction
|
日誌解讀說明
| 日誌訊息 |
意義 |
Getting transaction for [...] |
方法進入,事務攔截器開始處理 |
Creating new transaction |
建立新的事務(PROPAGATION_REQUIRED 時,若無現有事務) |
Participating in existing transaction |
加入現有事務(PROPAGATION_REQUIRED,上層已有事務) |
Committing JDBC transaction |
事務正常提交 |
Rolling back JDBC transaction |
事務回滾(發生例外) |
常見問題:@Transactional 沒有作用
如果日誌中看到 Getting transaction for 但沒有 Creating new transaction,可能是:
- 方法是
private 的(Spring AOP 無法攔截)
- 同一個類別中直接呼叫(self-invocation 問題)
- 沒有設定
@EnableTransactionManagement
參考資料