首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 事務機制深度解析:ACID、隔離級別、PHP 實戰與不可回滾語句

     編輯:MySQL 綜合教學

MySQL 事務機制深度解析:ACID、隔離級別、PHP 實戰與不可回滾語句

事務是關聯式資料庫可靠性的基石。本文從 InnoDB 架構視角切入,系統講解 ACID 實現、四大隔離級別與鎖關係、PHP mysqli 事務模板、以及 DDL 隱性提交 等實戰陷阱。

核心前提:唯有 InnoDB 支援事務

CREATE TABLE employee (...) ENGINE=InnoDB;
CREATE TABLE telephone (...) ENGINE=InnoDB;

MyISAM、MEMORY 等引擎不支援事務,操作即時生效,無回滾能力。

ACID 在 InnoDB 中的落地

特性InnoDB 實現機制
Atomicity (原子性)Undo Log 記錄反向操作,Crash Recovery 時回滾未提交事務
Consistency (一致性)Foreign Key、Check Constraint、Trigger + 原子性保證
Isolation (隔離性)MVCC + Row Lock + Gap Lock + Next-Key Lock
Durability (持久性)Redo Log (WAL) + Doublewrite Buffer + innodb_flush_log_at_trx_commit=1

四大隔離級別與現象對照

隔離級別髒讀不可重複讀幻讀InnoDB 鎖策略
READ UNCOMMITTED✅✅✅無鎖,極少用
READ COMMITTED❌✅✅行鎖,無 Gap Lock
REPEATABLE READ (預設)❌❌❌*Next-Key Lock 防幻讀
SERIALIZABLE❌❌❌表鎖/全範圍鎖,併發極低

* RR 級別下 InnoDB 透過 Next-Key Lock 實質上解決了幻讀,但純 MVCC 快照讀仍可能見到幻影,需 SELECT ... FOR UPDATE 或 LOCK IN SHARE MODE 加鎖讀。

PHP mysqli 事務範本 (生產級)

<?php
$mysqli = new mysqli('localhost', 'app', '****', 'biz_db');
$mysqli->autocommit(false);  // 關閉自動提交

$ok = true;
try {
    // 業務邏輯 1
    $stmt = $mysqli->prepare("INSERT INTO employee (first_name,last_name,job_title,salary) VALUES (?,?,?,?)");
    $stmt->bind_param('sssd', 'Grace', 'Williams', 'Software Engineer', 5000);
    if (!$stmt->execute()) throw new Exception($stmt->error);
    $emp_id = $mysqli->insert_id;  // 取得自增 ID

    // 業務邏輯 2 (依賴上一步 ID)
    $stmt = $mysqli->prepare("INSERT INTO telephone (employee_id, type, no) VALUES (?,?,?)");
    $stmt->bind_param('iss', $emp_id, 'mobile', '270-598712');
    if (!$stmt->execute()) throw new Exception($stmt->error);

    $mysqli->commit();
    echo "Transaction committed. New employee ID: $emp_id";
} catch (Exception $e) {
    $mysqli->rollback();
    error_log("TX rollback: " . $e->getMessage());
    http_response_code(500);
    echo "Operation failed, rolled back.";
} finally {
    $mysqli->autocommit(true);  // 還原
    $mysqli->close();
}

關鍵最佳實踐

  1. 事務要短:網路延遲、使用者思考時間不可放在事務內,否則長持鎖導致併發崩潰。
  2. 異常必須 Rollback:捕捉所有 Exception,確保 rollback() 執行。
  3. 死鎖重試:捕捉 mysqli_errno=1213,指數退避重試 3 次。
  4. 隔離級別按需設定:
    $mysqli->query("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED");
    高併發報表查詢可降級 RC 減少鎖競爭。

⚠️ 不可回滾的隱性提交語句 (必須知曉)

以下語句會隱性提交當前事務,導致前面操作無法回滾:

  • DDL:CREATE/ALTER/DROP TABLE, CREATE/DROP INDEX, TRUNCATE TABLE
  • 資料庫管理:CREATE/DROP DATABASE, RENAME TABLE
  • 鎖/解鎖:LOCK TABLES, UNLOCK TABLES
  • 備份/載入:LOAD DATA INFILE, LOAD XML
  • 複寫控制:START/STOP REPLICA, CHANGE REPLICATION SOURCE
  • 帳號管理:GRANT/REVOKE, SET PASSWORD

鐵律:事務中絕不執行 DDL。需變更結構請另開 Session、維護窗口或用 pt-online-schema-change。

驗證事務狀態

-- 查看當前隔離級別
SELECT @@transaction_isolation;

-- 查看活躍事務
SELECT * FROM information_schema.INNODB_TRX\G

-- 查看鎖等待
SELECT * FROM information_schema.INNODB_LOCK_WAITS\G

結語:事務不是萬能藥,濫用長事務是資料庫殺手。理解 InnoDB MVCC 與鎖機制、避開隱性提交陷阱、編寫「短小精悍、異常必滾、死鎖重試」的事務程式碼,才能在高併發下守住資料一致性防線。

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