ROLLBACK ไม่ทำงานหลังจาก INSERT INTO สร้างตารางปลายทางใหม่


11

ฉันกำลังทำงานกับสคริปต์ PHP ซึ่งนำเข้าไฟล์ CSV ( customers.csv) ลงในตาราง MySQL (customers )

ก่อนที่จะแทรกเนื้อหาของไฟล์ CSV ลงในตาราง mysql ฉันสำรองข้อมูลcustomersตารางดั้งเดิมก่อน

ฉันกำลังห่อกระบวนการนำเข้าทั้งหมด (รวมถึงการสำรองข้อมูล) ในธุรกรรม mysql (เพื่อพิจารณากรณีที่ CSV เสียหายที่ไหนสักแห่งที่อยู่ตรงกลางและเพื่อให้แน่ใจว่าการนำเข้านั้นเป็นอะตอม)

ปัญหาคือว่าย้อนกลับดูเหมือนจะไม่ทำงานเมื่อฉันเรียกมันว่าหลังจากที่INSERT INTOคำสั่ง: เมื่อตรวจสอบฐานข้อมูลผ่านทาง phpMyAdmin ฉันสามารถดูตารางที่สร้างขึ้นใหม่และแถวภายในมันยังคงอยู่หลังจาก 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เพราะมันเกี่ยวข้องกับการแทรกแถว (ไม่ได้กำหนดสคีมา) จริง ๆ แล้วจะทำธุรกรรมและหลังจากย้อนกลับฉันจะถูกทิ้งไว้กับตารางปลายทางที่ว่างเปล่า ทำไมมันไม่เป็นเช่นนั้น?

และนี่คือผลลัพธ์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 ขอบคุณสำหรับการแก้ไข
ypercubeᵀᴹ

1
และ @RolandoMySQLDBA สำหรับคำพูดของคุณ ฉันเป็น FGITW วันนี้ (และเร็วกว่าคุณเพียง 15 วินาที)
ypercubeᵀᴹ

@percube ยินดีต้อนรับ! ฉันต้องใช้เวลาสักพักกว่าจะคิดว่า CREAT TABLE นี้จะcause an implicit commit... ดังนั้นจึงต้องทำโครงร่างนี้บนกระดาษอย่างไรก็ตาม :) @RolandoMySQLDBA ขอบคุณสำหรับการป้อนข้อมูลที่รวดเร็วเช่นกัน ฉันอ่านคำตอบของคุณไม่กี่สิบครั้งในปีที่ผ่านมาและพวกเขาช่วยฉันได้มาก !!
Dimitry K

ดังนั้นคุณกำลังจะบอกว่านัยกระทำก่อนที่จะINSERTที่เกิดจากคำสั่ง DDL ยังอย่างใดทำให้เกิดการกระทำหลังจากแทรก?
mustaccio

1
ใช่มีสองส่วนในการให้เหตุผล แต่ส่วนหลักในความคิดของฉันว่า OP ไม่สามารถคิดออกได้คือการกระทำโดยนัยโดยสร้างตาราง
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.