資料庫事務是保證數據一致性的基石。本文系統講解 ACID 四大特性,對比 MyISAM/InnoDB 引擎差異,並給出基於 mysqli 與 PDO 兩種主流擴展的標準事務代碼範本,助你寫出健壯的金融級業務邏輯。
| 引擎 | 事務支援 | 鎖粒度 | 適用場景 |
|---|---|---|---|
| MyISAM | ❌ 不支援 | 表級鎖 | 純讀取、日誌、非關鍵數據 |
| InnoDB | ✅ 完整 ACID | 行級鎖 | 高併發寫入、金融業務、主流業務表 |
| BerkeleyDB | ✅ 支援 | 頁級鎖 | 較少見,歷史遺留項目 |
結論:涉及事務的表強制使用 InnoDB,建庫時預設即為 InnoDB(MySQL 5.5+)。
$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 = 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();
}
ALTER TABLE),會隱式提交事務。SQLSTATE[HY000]: General error: 1213 Deadlock 時,指數退避重試 2-3 次。在框架或項目中,可封裝 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 後端工程師進階的必修課。