運營反饋訂單提交卡住,應用與 DB 負載正常,無鎖等待。通過 INNODB_TRX 發現兩個事務長期 RUNNING,定位到具體 SQL 與應用 IP,最終在 Java 代碼中發現 catch (SQLException e) { } 吞噬異常且未 rollback(),導致事務懸掛。
SELECT * FROM information_schema.INNODB_TRX\G → 獲取 trx_mysql_thread_id。SELECT * FROM information_schema.PROCESSLIST WHERE ID=trx_mysql_thread_id → 獲取客戶端 IP:Port。try {
// 多條 DML
} catch (SQLException e) {
// 空 catch,未 rollback,未拋出
}
異常發生後未 rollback(),連接歸還池時仍處於事務中,後續複用該連接的請求會被阻塞或髒讀,最終導致業務卡死。
| 規範 | 代碼模板 |
|---|---|
| 必須 rollback | Connection conn = null;
try {
conn = ds.getConnection();
conn.setAutoCommit(false);
// ... DML
conn.commit();
} catch (SQLException e) {
if (conn != null) conn.rollback();
throw new BizException(e);
} finally {
if (conn != null) conn.close();
} |
| 使用 Spring @Transactional | 聲明式事務自動回滾 RuntimeException/Error,rollbackFor=Exception.class 覆蓋檢查型異常。 |
| 連接池驗證 | HikariCP connectionTestQuery=SELECT 1、maxLifetime 避免殭屍連接。 |
INNODB_TRX 過濾 trx_started < NOW() - INTERVAL 60 SECOND 告警。