ROLLBACK не працює після введення в новостворену таблицю призначення


11

Я працюю над PHP-скриптом, який імпортує файл CSV ( customers.csv) у таблицю MySQL ( customers).

Перш ніж вставляти вміст CSV-файлу в таблицю mysql, я спочатку створюю резервну копію оригінальної customersтаблиці.

Я завершую весь процес імпорту (включаючи резервне копіювання) транзакцією mysql (щоб врахувати випадки, коли CSV пошкоджений десь посередині, і щоб переконатися, що імпорт є атомним).

Проблема полягає в тому, що ROLLBACK, здається, не працює, коли я викликаю його відразу після INSERT INTOзаяви: при перевірці бази даних через phpMyAdmin я можу побачити новостворену таблицю І ROWS INSIDE IT, яка все ще присутня після відкату .

Ось журнал операцій:

[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, транзакція не скасовується. Я розумію, що 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, insert, rollback?
ypercubeᵀᴹ

Я збирався це сказати !!!
RolandoMySQLDBA

Чи вимкнено автоматичне ввімкнення підключення у програмі?
мустаччо

Відповіді:


13

Причина полягає в тому, що деякі твердження, як-от, 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виписки або використовувати тимчасову таблицю.


@Dimitry, thnx для редагування.
ypercubeᵀᴹ

1
І @RolandoMySQLDBA за добрі слова. Я сьогодні FGITW (і лише на 15 секунд швидший за вас;)
ypercubeᵀᴹ

@ypercube ласкаво просимо! Мені знадобилось певний час, щоб зрозуміти, де саме буде ця ТВОРЧА СТОЛИНА cause an implicit commit... Тож довелося все-таки робити цей контур на папері :) @ RoolandoMySQLDBA спасибі за швидке введення. Я прочитав кілька десятків ваших відповідей за останній рік, і вони мені дуже допомогли !!
Димитрій К

Так ви говорите , що неявне зобов'язання передINSERT тим , викликане твердженням DDL, а також яким - то чином призводить до фіксації після вставки?
мустаччо

1
Так, у міркуваннях є дві частини, але головна частина, на мою думку, те, що ОП не змогла з'ясувати, - це неявна фіксація таблиці створення.
ypercubeᵀᴹ

3

Схоже, порядок висловлювань викликає проблему.

У моєму старому блокуванні рядків після запису в транзакції ACID innodb я назвав 12 тверджень, які переривають транзакцію з перервами. У вашому конкретному випадку це була CREATE TABLEзаява.

Після того, як ви запустили CREATE TABLEвсередину START TRANSACTION... COMMIT/ROLLBACKблоку, не було рамки для відкату.

Просто запустіть CREATE TABLEраніше, START TRANSACTIONі вам повинно бути добре.

Спробувати !!!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.