首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP MySQL 事務處理:確保多表操作原子性的完整實現

     編輯:PHP 相關知識

當業務邏輯涉及多張表的寫入操作(如註冊初始化多張關聯表、問答回覆同時更新問題與回答表),單條 SQL 失敗會導致資料不一致。MySQL 事務透過「全成功提交、一失敗回滾」特性完美解決此問題。本文提供基於 mysqli 的事務封裝類方法。

事務處理核心代碼

/**
 * 批量 SQL 事務執行
 * @param string $password 資料庫密碼(或配置識別)
 * @param array  $sqls     SQL 陣列
 * @return bool            全部成功 true / 任一失敗 false
 */
public function doArraySqlActionsTran($password, $sqls) {
    $db = $this->doSqlLink($password); // 建立 mysqli 連線
    $db->autocommit(FALSE);            // 關閉自動提交,開啟事務

    $results = [];
    foreach ($sqls as $sql) {
        $results[] = $db->query($sql); // 執行每條 SQL
    }

    // 檢查執行結果
    $hasFailure = false;
    foreach ($results as $res) {
        if ($res === false) {
            $hasFailure = true;
            break;
        }
    }

    if ($hasFailure) {
        $db->rollback();               // 回滾所有操作
        $db->autocommit(TRUE);         // 恢復自動提交
        $db->close();
        return false;
    } else {
        $db->commit();                 // 提交事務
        $db->autocommit(TRUE);
        $db->close();
        return true;
    }
}

關鍵點解析

步驟方法說明
1. 關閉自動提交autocommit(FALSE)MySQL 預設每條 SQL 立即提交,必須關閉才能進入事務模式
2. 執行 SQL 群query()依序執行,若中途失敗後續仍會執行(除非手動中斷),最終由結果判斷
3. 結果判斷遍歷結果陣列任一 false 即視為失敗
4. 回滾/提交rollback() / commit()原子性保證:要麼全做,要麼全不做
5. 恢復自動提交autocommit(TRUE)釋放連線回連線池時恢復預設行為

進階優化建議

  • 預處理語句:使用 prepare() + bind_param() 防 SQL 注入並提升重複執行效能。
  • 錯誤資訊記錄:回滾前記錄 $db->error、失敗的 SQL 及參數,便於事後排查。
  • 死鎖重試:InnoDB 死鎖(Error 1213)可捕獲後指數退避重試 3 次。
  • 異常處理模式:配合 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 拋出異常,使用 try-catch 結構更清晰。

異常處理版本範例(推薦現代專案)

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
    $db = new mysqli($host, $user, $pass, $dbname);
    $db->begin_transaction(); // 等同 autocommit(FALSE)
    foreach ($sqls as $sql) {
        $db->query($sql);
    }
    $db->commit();
    return true;
} catch (mysqli_sql_exception $e) {
    $db->rollback();
    error_log('Transaction failed: ' . $e->getMessage());
    return false;
} finally {
    $db->close();
}

適用場景對照

  • ✅ 註冊流程:users + profiles + wallets + logs 多表寫入
  • ✅ 訂單建立:orders + order_items + inventory_expiration + coupons
  • ✅ 轉帳操作:from_account - 金額、to_account + 金額、transfer_logs
  • ❌ 單表查詢/單表寫入:無需事務開銷
  • ❌ 跨資料庫/跨引擎(MyISAM 不支援事務)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved