새로 작성된 대상 테이블을 삽입 한 후 ROLLBACK이 작동하지 않습니다.


11

CSV 파일 ( customers.csv)을 MySQL 테이블 ( customers) 로 가져 오는 PHP 스크립트를 작성 중 입니다.

CSV 파일의 내용을 mysql 테이블에 삽입하기 전에 먼저 원래 customers테이블을 백업 합니다.

전체 가져 오기 프로세스 (백업 포함)를 mysql 트랜잭션으로 래핑하고 있습니다 (중간 어딘가에 CSV가 손상된 경우를 고려하고 가져 오기가 원자적임을 보장하기 위해).

문제는 ROLLBACK이 INSERT INTO명령문 직후에 호출 할 때 작동하지 않는 것 입니다.

작업 로그는 다음과 같습니다.

[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" [] []

그래서 왜 depsite 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

그리고 desination 테이블에 대한 출력은 다음과 같습니다.

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

프로그램의 연결에서 자동 커밋을 비활성화합니까?
mustaccio

답변:


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 환영합니다! 정확히이 CREAT TABLE이 어디에 있는지 알아내는 데 시간이 걸렸습니다 cause an implicit commit... 어쨌든 종이 에이 개요를 수행해야했습니다 :) @RolandoMySQLDBA 빠른 입력에 감사드립니다. 작년에 수십 개의 답글을 읽었으며 많은 도움을 받았습니다 !!
Dimitry K

그래서 당신은 암시 적 커밋 말을하는지 전에INSERT 도 어떻게 든 커밋 원인의 DDL 문에 의해 발생 삽입?
mustaccio

1
예, 추론에는 두 부분이 있지만 내 의견으로는 OP가 파악할 수 없다는 주요 부분은 create 테이블의 암시 적 커밋이었습니다.
ypercubeᵀᴹ

3

명령문의 순서가 문제의 원인 인 것 같습니다.

ACID 트랜잭션 innodb 내 오래된 포스트 행 잠금에서 트랜잭션을 간헐적으로 중단하는 12 개의 명령문을 지정했습니다. 당신의 특별한 경우에, 그것은 CREATE TABLE진술이었습니다.

... 블록 CREATE TABLE내부 를 실행 한 후에는 롤백 할 프레임 워크가 없었습니다.START TRANSACTIONCOMMIT/ROLLBACK

CREATE TABLE이전을 실행하면 START TRANSACTION괜찮을 것입니다.

시도 해봐 !!!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.