Mysql

INSERT INTO 新創建的目標表後 ROLLBACK 不起作用

  • January 19, 2015

我正在研究將 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或使用臨時表。

引用自:https://dba.stackexchange.com/questions/89638