Mysql
INSERT INTO 新創建的目標表後 ROLLBACK 不起作用
我正在研究將 CSV 文件 (
customers.csv
) 導入 MySQL 表 (customers
) 的 PHP 腳本。在將 CSV 文件的內容插入 mysql 表之前,我首先備份原始
customers
表。我將整個導入過程(包括備份)包裝在一個 mysql 事務中(以考慮 CSV 在中間某處損壞的情況,並確保導入是原子的)。
問題是當我在語句之後立即呼叫它時 ROLLBACK 似乎不起作用
INSERT INTO
:當通過 phpMyAdmin 檢查數據庫時,我可以看到新創建的表和 ROWS INSIDE 在 roollback 之後仍然存在。以下是操作日誌:
[2015-01-19 14:08:11] DEBUG: "START TRANSACTION" [] [] [2015-01-19 14:08:11] DEBUG: SHOW TABLES LIKE :table_name; [] [] [2015-01-19 14:08:28] DEBUG: CREATE TABLE `customers__20150119_14_08_20` LIKE `customers` [] [] [2015-01-19 14:08:37] DEBUG: INSERT INTO `customers__20150119_14_08_20` SELECT * FROM `customers` [] [] [2015-01-19 14:08:50] DEBUG: "ROLLBACK" [] []
所以我想知道為什麼
ROLLBACK
呼叫depsite,事務沒有被取消。我明白這CREATE TABLE
本質上不是事務性的,不能回滾。但我假設INSERT INTO
因為它處理插入行(不定義模式),實際上將是事務性的,並且在 ROLLBACK 之後我將留下空的目標表。為什麼不是這樣?這是輸出
SHOW CREATE TABLE customers
(所以我的表是InnoDb
):CREATE TABLE `customers` ( `Code` varchar(32) NOT NULL, `Name` varchar(128) DEFAULT NULL, `Price` varchar(128) DEFAULT NULL, PRIMARY KEY (`Code`), KEY `Price` (`Price`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
這是目的地表的輸出:
CREATE TABLE `customers__20150119_14_08_20` ( `Code` varchar(32) NOT NULL, `Name` varchar(128) DEFAULT NULL, `Price` varchar(128) DEFAULT NULL, PRIMARY KEY (`Code`), KEY `Price` (`Price`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
原因是某些語句,如
CREATE TABLE
導致隱式送出。您可以在文件中閱讀它們:導致隱式送出的語句。所以原始的語句序列:
START TRANSACTION SHOW TABLES LIKE customers CREATE TABLE `customers__20150119_14_08_20` LIKE `customers` INSERT INTO `customers__20150119_14_08_20` SELECT * FROM `customers` ROLLBACK
將擴展為:
START TRANSACTION ; -- transaction context created SHOW TABLES LIKE customers ; COMMIT ; -- CREATE TABLE forces commit before itself -- (at this point the previous transaction is done.) START TRANSACTION ; -- and a new transaction CREATE TABLE `customers__20150119_14_08_20` LIKE `customers` ; COMMIT ; -- CREATE TABLE forces commit after itself. -- At this point there's no transaction context START TRANSACTION ; -- starts a new transaction INSERT INTO `customers__20150119_14_08_20` SELECT * FROM `customers` ; COMMIT ; -- caused by "autocommit on" setting (guess). ROLLBACK ; -- this rollback HAS NOTHING to undo
解決方案是在語句之後啟動事務(或新事務)
CREATE TABLE
或使用臨時表。