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

PHP 操作 MySQL 事務完整指南:ACID 原則與 mysqli/PDO 實戰

     編輯:PHP 相關知識

PHP 操作 MySQL 事務完整指南:ACID 原則與 mysqli/PDO 實戰

資料庫事務是保證數據一致性的基石。本文系統講解 ACID 四大特性,對比 MyISAM/InnoDB 引擎差異,並給出基於 mysqli 與 PDO 兩種主流擴展的標準事務代碼範本,助你寫出健壯的金融級業務邏輯。

ACID 四大特性通俗解讀

  • 原子性:事務內所有操作要么全成功,要么全失敗回滾。例:轉賬必須同時扣款與入賬。
  • 一致性:事務前後數據庫從一個合法狀態變換到另一個合法狀態,不違反完整性約束。
  • 隔離性:併發事務互不干擾,透過鎖機制(如 InnoDB 行級鎖)實現。
  • 持久性:提交後的修改永久保存,即使系統崩潰也能恢復(依賴 Redo Log)。

引擎選擇:必須用 InnoDB

引擎事務支援鎖粒度適用場景
MyISAM❌ 不支援表級鎖純讀取、日誌、非關鍵數據
InnoDB✅ 完整 ACID行級鎖高併發寫入、金融業務、主流業務表
BerkeleyDB✅ 支援頁級鎖較少見,歷史遺留項目

結論:涉及事務的表強制使用 InnoDB,建庫時預設即為 InnoDB(MySQL 5.5+)。

mysqli 面向對象事務範本

$mysqli = new mysqli('localhost', 'root', '', 'DB_Lib2Test');
if ($mysqli->connect_errno) {
    die('連接失敗: ' . $mysqli->connect_error);
}

$mysqli->autocommit(false); // 開啟事務

$sql1 = "UPDATE User SET ScoreCount = ScoreCount + 10 WHERE ID = '123456'";
$sql2 = "UPDATE ScoreDetail SET FScore = 300 WHERE ID = '123456'";
$sql3 = "INSERT INTO ScoreDetail (ID, Score) VALUES ('123456', 60)";

try {
    $mysqli->query($sql1);
    $mysqli->query($sql2);
    $mysqli->query($sql3);
    $mysqli->commit();
    echo '事務提交成功';
} catch (mysqli_sql_exception $e) {
    $mysqli->rollback();
    echo '事務回滾: ' . $e->getMessage();
} finally {
    $mysqli->autocommit(true); // 恢復自動提交
    $mysqli->close();
}

PDO 事務範本(推薦,支援多數據庫)

$pdo = new PDO('mysql:host=localhost;dbname=DB_Lib2Test;charset=utf8mb4', 'root', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

try {
    $pdo->beginTransaction();

    $pdo->exec("UPDATE User SET ScoreCount = ScoreCount + 10 WHERE ID = '123456'");
    $pdo->exec("UPDATE ScoreDetail SET FScore = 300 WHERE ID = '123456'");
    $pdo->exec("INSERT INTO ScoreDetail (ID, Score) VALUES ('123456', 60)");

    $pdo->commit();
    echo '事務提交成功';
} catch (PDOException $e) {
    $pdo->rollBack();
    echo '事務回滾: ' . $e->getMessage();
}

常見坑點與最佳實踐

  1. 不要在事務中執行 DDL(如 ALTER TABLE),會隱式提交事務。
  2. 控制事務大小:長事務佔用鎖資源久,易導致死鎖或主從延遲;拆分為多個小事務或用隊列異步處理。
  3. 異常捕獲要精確:僅捕獲數據庫異常,業務邏輯異常拋出給上層處理。
  4. 死鎖重試機制:捕獲 SQLSTATE[HY000]: General error: 1213 Deadlock 時,指數退避重試 2-3 次。
  5. 關閉自動提交後務必成對 commit/rollback,否則連接釋放時隱式回滾,導致數據「莫名消失」。

封裝建議:基類或 Trait 統一事務控制

在框架或項目中,可封裝 transactional(callable $callback) 方法,自動處理 begin/commit/rollback/異常,業務代碼僅需專注 SQL 邏輯:

function transactional(PDO $pdo, callable $callback) {
    $pdo->beginTransaction();
    try {
        $result = $callback($pdo);
        $pdo->commit();
        return $result;
    } catch (Throwable $e) {
        $pdo->rollBack();
        throw $e;
    }
}

// 使用
transactional($pdo, function($pdo) {
    $pdo->exec("UPDATE ...");
    $pdo->exec("INSERT ...");
});

掌握事務核心原理與規範代碼模式,是 PHP 後端工程師進階的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved