刪除用戶時需同步刪除基本信息、郵件、文章等多張表。若中途失敗且無事務,數據將處於「半刪除」不一致狀態,後果嚴重。
| 特性 | 含義 | MySQL 實現 |
|---|---|---|
| 原子性 | 要麼全做,要麼全不做 | Undo Log 回滾 |
| 一致性 | 事務前後數據庫滿足所有約束 | 約束檢查 + 原子性 |
| 隔離性 | 並發事務互不干擾 | MVCC + 鎖(RR 級默認) |
| 持久性 | 提交後永久生效,故障可恢復 | Redo Log + 雙寫緩衝 |
SHOW VARIABLES LIKE 'have_%';
-- have_innodb = YES 才能用事務
BEGIN; -- 或 START TRANSACTION
INSERT INTO dbtest VALUES (5);
INSERT INTO dbtest VALUES (6);
COMMIT; -- 確認提交
BEGIN;
INSERT INTO dbtest VALUES (7);
ROLLBACK; -- 回滾,7 不會寫入
SET autocommit = 0; -- 關閉自動提交,後續所有語句隱式在一個事務中
... 多條 DML ...
COMMIT; -- 結束當前事務,**同時隱式開啟下一個事務**
SET autocommit = 1; -- 恢復自動提交
陷阱: autocommit=0 下,COMMIT 同時開啟新事務,易導致長事務未覺察。生產環境強烈建議顯式 BEGIN/COMMIT。
function Tran(array $sqlList) {
$judge = 1;
mysql_query('BEGIN');
foreach ($sqlList as $sql) {
if (!mysql_query($sql)) { $judge = 0; break; }
}
if ($judge) {
mysql_query('COMMIT');
return true;
} else {
mysql_query('ROLLBACK');
return false;
}
}
// 使用
$sqls = [
"INSERT INTO trans (id) VALUES ('2')",
"INSERT INTO trans (id) VALUES ('4')"
];
Tran($sqls);
$pdo = new PDO("mysql:host=localhost;dbname=test", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$pdo->beginTransaction();
$pdo->exec("INSERT INTO trans (id) VALUES ('2')");
$pdo->exec("INSERT INTO trans (id) VALUES ('4')");
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
LOCK TABLES t1 WRITE, t2 READ; — 顯式鎖表,**會隱式提交當前事務**。SELECT ... FOR UPDATE)配合索引。autocommit=0,改用顯式 BEGIN/COMMIT/ROLLBACK。一句話總結: InnoDB + 顯式 BEGIN/COMMIT/ROLLBACK + 短小事務 = 可靠的數據一致性保障。