事務是數據一致性的基石。本文涵蓋 MySQL InnoDB 引擎啟用驗證、PHP PDO 事務完整代碼模板、異常回滾模式、自動提交控制,幫助 PHPer 快速落地可靠的寫入邏輯。
my.cnf 取消註釋 #skip-innodb → skip-innodb(若存在),重啟。default-storage-engine=InnoDB,重啟。SHOW ENGINES; 確認 InnoDB Support = YES/DEFAULT。
<?php
try {
// 1. 建立連接
$pdo = new PDO("mysql:host=xxxx;dbname=xxxx;charset=utf8mb4", "xxxx", "xxxx");
// 2. 異常模式:SQL 錯誤拋出 PDOException
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 3. 關鍵:關閉自動提交,開啟事務邊界
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
} catch (PDOException $e) {
die("DB連接失敗: " . $e->getMessage());
}
try {
// 4. 顯式開啟事務
$pdo->beginTransaction();
$price = 500;
// 5. 業務 SQL
$sql1 = "UPDATE zhanghao SET price = price - {$price} WHERE id = 1";
$affected1 = $pdo->exec($sql1);
if ($affected1 === 0) throw new Exception("扣款失敗:id=1 不存在或餘額不足");
$sql2 = "UPDATE zhanghao SET price = price + {$price} WHERE id = 2";
$affected2 = $pdo->exec($sql2);
if ($affected2 === 0) throw new Exception("入賬失敗:id=2 不存在");
// 6. 提交事務
$pdo->commit();
echo "交易成功";
} catch (Exception $e) {
// 7. 任意異常 → 回滾
$pdo->rollBack();
echo "交易失敗並回滾: " . $e->getMessage();
}
?>
| 屬性/方法 | 作用 | 注意事項 |
|---|---|---|
ATTR_ERRMODE => ERRMODE_EXCEPTION | SQL 錯誤拋出異常,避免靜默失敗 | 必開,否則需手動檢查 errorCode/errorInfo |
ATTR_AUTOCOMMIT => 0 | 關閉自動提交,手動控制事務邊界 | 與 beginTransaction() 配套使用 |
beginTransaction() | 啟動事務(發送 START TRANSACTION) | 巢狀事務不支持,會拋異常 |
commit() | 提交事務 | 成功才持久化 |
rollBack() | 回滾事務 | 捕獲異常後必須調用 |
exec() | 執行 DML,返回影響行數 | 不返回結果集 |
lastInsertId() | 獲取上條 INSERT 自增 ID | 需在同一連接、事務提交前調用 |
SHOW TABLE STATUS LIKE 't%'; 驗證 Engine=InnoDB。CREATE/DROP/ALTER/TRUNCATE 會隱式提交前面操作,打破原子性。SQLSTATE[HY000]: General error: 1213 Deadlock found,指數退避重試 3 次。Exception 而非 PDOException,覆蓋業務邏輯拋出的自定義異常。事務不僅是 BEGIN/COMMIT,更是對數據一致性承諾的代碼體現。嚴格遵循「異常即回滾、業務驗證前置、長事務拆分」三原則,線上零事故。