Contents

在日誌中顯示Spring事務

每次設定 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,可能是:

  1. 方法是 private 的(Spring AOP 無法攔截)
  2. 同一個類別中直接呼叫(self-invocation 問題)
  3. 沒有設定 @EnableTransactionManagement

參考資料