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

MySQL 事務保存點:實現部分回滾的關鍵技術

     編輯:MySQL 綜合教學

MySQL 事務保存點:實現部分回滾的關鍵技術

事務通常是「全提交或全回滾」,但業務有時需要「提交前置操作,回滾後續嘗試」。MySQL SAVEPOINT 機制完美解決此需求。

核心語法

語句作用
SAVEPOINT savepoint_name在當前事務中標記一個保存點
ROLLBACK TO SAVEPOINT savepoint_name回滾到指定保存點,釋放該點之後的鎖,保留之前的操作
RELEASE SAVEPOINT savepoint_name顯式釋放保存點(不影響數據),節省內存

完整演示流程

-- 1. 準備表
CREATE TABLE `user` (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
INSERT INTO `user` VALUES (1, 'Alice');

-- 2. 開啟事務
START TRANSACTION;

-- 3. 插入第 1 條
INSERT INTO `user` VALUES (2, 'Bob');

-- 4. 插入第 2 條
INSERT INTO `user` VALUES (3, 'Carol');

-- 5. 設置保存點
SAVEPOINT after_two;

-- 6. 插入第 3 條(可能失敗的業務嘗試)
INSERT INTO `user` VALUES (4, 'Dave');

-- 7. 假設業務判斷失敗,回滾到保存點
ROLLBACK TO SAVEPOINT after_two;

-- 8. 查看結果:只有 Alice, Bob, Carol(id=1,2,3)
SELECT * FROM `user`;

-- 9. 繼續其他操作或提交
COMMIT;

關鍵特性

  • 保留鎖:ROLLBACK TO SAVEPOINT 釋放保存點後獲取的鎖,保留之前的鎖
  • 可多次回滾:同一保存點可多次 ROLLBACK TO
  • 嵌套保存點:可設置多個不同名稱的保存點,形成棧結構
  • COMMIT 清除所有保存點,ROLLBACK(無 TO)回滾整個事務並清除保存點

實戰場景:訂單創建與庫存扣減

START TRANSACTION;

-- 1. 創建訂單主表(核心,必須成功)
INSERT INTO orders (user_id, total) VALUES (1001, 299.00);
SET @order_id = LAST_INSERT_ID();

-- 2. 寫入訂單項(核心)
INSERT INTO order_items (order_id, sku_id, qty, price) VALUES 
(@order_id, 1001, 1, 199.00),
(@order_id, 1002, 2, 50.00);

SAVEPOINT after_core; -- 核心業務完成

-- 3. 嘗試扣減庫存(可能失敗:庫存不足、並發衝突)
UPDATE products SET stock = stock - 1 WHERE id = 1001 AND stock >= 1;
UPDATE products SET stock = stock - 2 WHERE id = 1002 AND stock >= 2;

-- 4. 檢查庫存扣減結果
IF ROW_COUNT() < 2 THEN
    ROLLBACK TO SAVEPOINT after_core; -- 僅回滾庫存操作,保留訂單
    -- 記錄庫存不足日誌、發送補貨通知
    INSERT INTO stock_alert (sku_id, reason) VALUES (1001, 'INSUFFICIENT');
ELSE
    -- 庫存扣減成功,繼續發送通知、積分等非核心操作
    INSERT INTO notifications (order_id, type) VALUES (@order_id, 'CREATED');
END IF;

COMMIT;

對比:保存點 vs 內部事務(不支持)

MySQL 不支持嵌套事務(START TRANSACTION 會隱式提交前一個事務)。保存點是單事務內實現「部分提交/回滾」的唯一標準方式。

常見誤區

Q: ROLLBACK TO SAVEPOINT 後事務還活著嗎?
A: 是的,事務仍處於開啟狀態,可繼續執行 SQL 或 COMMIT/ROLLBACK。
Q: 保存點名稱區分大小寫嗎?
A: 不區分,SAVEPOINT abc 和 SAVEPOINT ABC 視為同一個。
Q: 異常拋出後自動回滾到保存點?
A: 不會。應用層捕獲異常後需顯式執行 ROLLBACK TO SAVEPOINT。

最佳實踐

  1. 保存點命名語義化:after_core、before_risky、before_external_call
  2. 及時 RELEASE SAVEPOINT 釋放不再需要的點,避免元數據膨脹
  3. 僅在單一事務內劃分階段使用,跨服務邊界請用分布式事務(Saga/TCC)

善用 SAVEPOINT,讓事務控制力度從「粗粒度全有或全無」進化為「細粒度可控回滾」。

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