ROLLBACK không hoạt động sau khi XÁC NHẬN VÀO bảng đích mới được tạo


11

Tôi đang làm việc trên tập lệnh PHP để nhập tệp CSV ( customers.csv) vào bảng MySQL ( customers).

Trước khi chèn nội dung của tệp CSV vào bảng mysql, trước tiên tôi sao lưu customersbảng gốc .

Tôi đang bao bọc toàn bộ quá trình nhập (bao gồm cả sao lưu) trong giao dịch mysql (để giải thích cho các trường hợp khi CSV bị hỏng ở đâu đó ở giữa và để đảm bảo nhập là nguyên tử).

Vấn đề là ROLLBACK dường như không hoạt động khi tôi gọi nó ngay sau INSERT INTOcâu lệnh: khi kiểm tra cơ sở dữ liệu qua phpMyAdmin tôi có thể thấy bảng mới được tạo VÀ ROWS TRONG NÓ vẫn hiện diện sau khi quay lại .

Đây là nhật ký của các hoạt động:

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

Vì vậy, tôi tự hỏi tại sao depsite ROLLBACKđược gọi, giao dịch không bị hủy. Tôi hiểu rằng đó CREATE TABLEkhông phải là giao dịch về bản chất và không thể quay trở lại. Nhưng tôi đã giả định rằng INSERT INTOvì nó liên quan đến việc chèn các hàng (không xác định lược đồ), SILL thực sự là giao dịch và sau ROLLBACK, tôi sẽ bị bỏ lại với bảng đích trống. Tại sao nó không phải là trường hợp?

Và đây là đầu ra SHOW CREATE TABLE customers(vì vậy bảng của tôi là 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

và đây là đầu ra cho bảng giảm dần:

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

Là hành vi giống nhau nếu bạn sắp xếp lại đầu tiên create table, sau đó start transaction, insert, rollback?
ypercubeᵀᴹ

Tôi chỉ định nói điều đó với !!!
RolandoMySQLDBA

Bạn có vô hiệu hóa autocommit trên kết nối trong chương trình của bạn không?
mustaccio

Câu trả lời:


12

Lý do là một số tuyên bố, như CREATE TABLEgây ra một cam kết ngầm. Bạn có thể đọc về chúng trong tài liệu: Tuyên bố gây ra một cam kết ngầm .

Vì vậy, chuỗi các báo cáo ban đầu:

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

sẽ mở rộng thành:

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

Giải pháp sẽ là bắt đầu giao dịch (hoặc một giao dịch mới) sau khi CREATE TABLEtuyên bố hoặc sử dụng bảng tạm thời.


@Dimitry, thnx để chỉnh sửa.
ypercubeᵀᴹ

1
Và @RolandoMySQLDBA cho những từ loại của bạn. Tôi là FGITW ngày hôm nay (và chỉ nhanh hơn bạn 15 giây;)
ypercubeᵀᴹ

@ypercube chào mừng! Tôi đã mất một thời gian để tìm ra chính xác nơi CREAT TABLE này sẽ cause an implicit commit... Vì vậy, tôi phải thực hiện phác thảo này trên giấy tờ :) @RolandoMyQueryDBA cũng cảm ơn vì đã nhập nhanh. Tôi đã đọc vài chục câu trả lời của bạn trong năm ngoái và họ đã giúp tôi rất nhiều !!
Dimitry K

Vì vậy, bạn đang nói rằng tiềm ẩn cam kết trước các INSERT, do lệnh DDL, cũng bằng cách nào đó gây ra một cam kết sau khi chèn?
mustaccio

1
Vâng, có hai phần về lý luận nhưng phần chính theo ý kiến ​​của tôi, rằng OP không thể hiểu được là cam kết ngầm của bảng tạo.
ypercubeᵀᴹ

3

Có vẻ như thứ tự của các báo cáo đang gây ra vấn đề.

Trong khóa bài cũ của tôi trong khóa giao dịch ACID , tôi đã đặt tên cho 12 câu lệnh phá vỡ giao dịch không liên tục. Trong trường hợp cụ thể của bạn, đó là CREATE TABLEtuyên bố.

Khi bạn chạy CREATE TABLEvào START TRANSACTION...COMMIT/ROLLBACK khối, không có khung để quay lại.

Chỉ cần chạy CREATE TABLEtrướcSTART TRANSACTION và bạn sẽ ổn.

Hãy thử một lần !!!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.