在資料庫操作中,事務 是一組不可分割的 SQL 語句序列。事務遵循 ACID 原則(原子性、一致性、隔離性、持久性),確保所有操作要麼全部成功提交,要麼全部失敗回滾。這對於銀行轉賬、訂單處理等涉及多步操作的業務場景至關重要。
假設用戶 A 轉帳 100 元給用戶 B,涉及兩個關鍵步驟:
若第一步成功但第二步失敗(如網路中斷、資料庫錯誤),資料將處於不一致狀態——A 的錢少了,B 卻沒收到。事務控制正是為了解決此問題。
autocommit(false):關閉自動提交,開啟事務模式commit():提交事務,永久保存變更rollback():回滾事務,撤銷所有未提交的變更<?php
// 1. 建立資料庫連線
$mysqli = new MySQLi("localhost", "root", "123456", "liuyan");
if ($mysqli->connect_error) {
die("連線失敗: " . $mysqli->connect_error);
}
$mysqli->query("SET NAMES 'utf8'"); // 建議使用 utf8
// 2. 關閉自動提交,啟動事務
$mysqli->autocommit(false);
// 3. 定義轉賬 SQL
$sql1 = "UPDATE account SET balance = balance - 100 WHERE id = 1;";
$sql2 = "UPDATE account SET balance = balance + 100 WHERE id = 2;";
// 4. 執行 SQL
$res1 = $mysqli->query($sql1);
$res2 = $mysqli->query($sql2);
// 5. 根據執行結果決定提交或回滾
if ($res1 && $res2) {
$mysqli->commit();
echo "轉賬成功!";
} else {
$mysqli->rollback();
echo "轉賬失敗:" . $mysqli->error;
}
// 6. 關閉連線
$mysqli->close();
?>
預設情況下,mysqli 每執行一條 SQL 就會自動提交。關閉後,所有查詢都在同一事務中,直到显式調用 commit() 或 rollback()。
生產環境建議使用 try-catch 捕獲異常,並記錄錯誤日誌:
try {
$mysqli->autocommit(false);
$mysqli->query($sql1);
$mysqli->query($sql2);
$mysqli->commit();
} catch (Exception $e) {
$mysqli->rollback();
error_log("轉賬異常: " . $e->getMessage());
}
MySQL 預設隔離級別為 REPEATABLE READ,可防止髒讀、不可重複讀、幻讀。高併發場景下可根據業務需求調整。
複雜業務邏輯可封裝在 MySQL 儲存過程中,由資料庫層面保證原子性,減少網路往返:
DELIMITER //
CREATE PROCEDURE transfer(IN from_id INT, IN to_id INT, IN amount DECIMAL(10,2))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
START TRANSACTION;
UPDATE account SET balance = balance - amount WHERE id = from_id;
UPDATE account SET balance = balance + amount WHERE id = to_id;
COMMIT;
END//
DELIMITER ;
PHP 僅需調用 CALL transfer(1, 2, 100) 即可。
掌握 mysqli 事務控制是 PHP 開發者處理金融、訂單等核心業務的必備技能。通過 autocommit(false)、commit()、rollback() 三大核心方法,配合嚴謹的錯誤處理,即可構建可靠的資料一致性保障機制。實際專案中,建議結合儲存過程、連線池、監控告警進一步提升系統穩定性。