DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @err = 1;DECLARE err INT DEFAULT 0;START TRANSACTION; / COMMIT; / ROLLBACK;DROP PROCEDURE IF EXISTS `createBusiness`;
CREATE PROCEDURE `createBusiness`(IN `p_count` INT)
BEGIN
-- 1. 變數宣告
DECLARE `v_flag` INT DEFAULT `p_count`;
DECLARE `v_uuid` CHAR(32);
DECLARE `v_now` TIMESTAMP;
DECLARE `v_err` INT DEFAULT 0;
-- 2. 異常處理器:捕捉任何 SQL 異常,設定錯誤標記
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET `v_err` = 1;
-- 3. 開啟事務
START TRANSACTION;
-- 4. 業務迴圈
WHILE `v_flag` > 0 DO
-- 生成不帶連字號的 UUID
SET `v_uuid` = REPLACE(UUID(), '-', '');
-- 當前時間戳
SET `v_now` = CURRENT_TIMESTAMP();
-- 核心插入邏輯
INSERT INTO `business_table` (
`id`, `title`, `keyword`, `has_image`, `is_today_head`,
`is_show_in_home`, `is_bigness`, `publish_time`,
`origin_id`, `modify_time`, `is_analysis`
) VALUES (
`v_uuid`,
CONCAT('事件標題', `v_flag`),
CONCAT('關鍵字', `v_flag`),
1, 1, 0, 0,
`v_now`,
CONCAT('xxxxxxx', `v_flag`),
`v_now`,
1
);
-- 迴圈計數器遞減
SET `v_flag` = `v_flag` - 1;
-- 測試用:模擬第 7 次失敗
-- IF `v_flag` = 7 THEN SET `v_err` = 1; END IF;
END WHILE;
-- 5. 根據錯誤標記提交或回滾
IF `v_err` = 0 THEN
COMMIT;
SELECT 'OK' AS `result`;
ELSE
ROLLBACK;
SELECT 'ERR' AS `result`;
END IF;
END;
| 語句 | 說明 |
|---|---|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION | 捕捉所有 SQL 錯誤(死鎖、重複鍵、外鍵違反等),不中斷過程,設標記 |
START TRANSACTION | 標記事務起點,InnoDB 開始記錄 Undo Log |
COMMIT | 持久化變更,釋放鎖 |
ROLLBACK | 利用 Undo Log 還原所有變更,釋放鎖 |
WHILE ... END WHILE | MySQL 儲存過程流程控制,注意 SET var = var - 1 無 -- 運算子 |
START TRANSACTION; SAVEPOINT sp1; -- 子操作 IF error THEN ROLLBACK TO SAVEPOINT sp1; END IF; -- 繼續其他操作 COMMIT;
注意:MySQL 不支援真正的嵌套事務,SAVEPOINT 是替代方案。
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;在儲存過程中正確使用事務,關鍵在於異常處理器 + 錯誤標記 + 顯式 COMMIT/ROLLBACK。掌握此模板,能確保批次業務操作的原子性,避免「半成功」導致資料不一致。