CodeIgniter 的事務機制判斷回滾條件為「SQL 語句是否執行成功」。但對於 UPDATE 操作,即使影響行數為 0(資料未實際變更),SQL 執行結果仍回傳成功,導致框架無法自動偵測業務邏輯上的失敗。
在一個包含多條 SQL 的事務中,若中間的 UPDATE 未匹配到資料(影響行數為 0),框架視為成功繼續執行後續語句,最終提交事務,造成資料不一致。
// 採用手動事務模式
$this->db->trans_strict(FALSE);
$this->db->trans_begin();
$this->db->query('SELECT ...'); // SELECT 無需特殊處理
$this->db->query('INSERT ...'); // INSERT 錯誤 CI 會自動處理
$this->db->query('UPDATE ...');
if (!$this->db->affected_rows()) { // UPDATE 失敗則手動回滾
$this->db->trans_rollback();
// 異常處理邏輯
exit(); // 終止後續 SQL 執行
}
$this->db->query('DELETE ...');
if (!$this->db->affected_rows()) { // DELETE 失敗則手動回滾
$this->db->trans_rollback();
// 異常處理邏輯
exit();
}
$this->db->query('SELECT ...');
$this->db->query('INSERT ...');
// 最終根據狀態提交或回滾
if ($this->db->trans_status() === TRUE) {
$this->db->trans_commit();
} else {
$this->db->trans_rollback();
// 異常處理
}
UPDATE/DELETE 操作,必須檢查 affected_rows() 確認業務邏輯是否生效。trans_start()/trans_complete())。trans_strict(FALSE) 避免嚴格模式下單一失敗導致全域回滾,配合手動控制更靈活。透過手動事務控制與行數檢查,可精準掌握每個寫入操作的真實結果,避免框架自動判斷的盲區。