ฉันกำลังทำงานกับโปรแกรมที่ออก DDL ฉันต้องการทราบว่าCREATE TABLE
DDL ที่คล้ายกันนี้สามารถย้อนกลับได้หรือไม่
- Postgres
- MySQL
- SQLite
- และคณะ
อธิบายว่าแต่ละฐานข้อมูลจัดการธุรกรรมกับ DDL อย่างไร
ฉันกำลังทำงานกับโปรแกรมที่ออก DDL ฉันต้องการทราบว่าCREATE TABLE
DDL ที่คล้ายกันนี้สามารถย้อนกลับได้หรือไม่
อธิบายว่าแต่ละฐานข้อมูลจัดการธุรกรรมกับ DDL อย่างไร
คำตอบ:
http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysisให้ภาพรวมของปัญหานี้จากมุมมองของ PostgreSQL
การทำธุรกรรม DDL เป็นไปตามเอกสารนี้หรือไม่
SQLite ดูเหมือนจะมี DDL แบบทรานแซคชันเช่นกัน ฉันสามารถROLLBACK
สร้างCREATE TABLE
คำสั่งใน SQLite ได้ ใช้CREATE TABLE
เอกสารไม่ได้พูดถึงการทำธุรกรรมใด ๆ เป็นพิเศษ 'gotchas'
ALTER TABLE
คำสั่ง SQLite ที่ค่อนข้าง จำกัดยังสามารถย้อนกลับได้ มันไม่ได้เป็นที่กล่าวถึงอย่างชัดเจนในเอกสาร สิ่งที่กล่าวถึงคือวิธีดำเนินการเปลี่ยนแปลง "ขั้นสูง" ภายในธุรกรรม
PostgreSQL มี DDL แบบธุรกรรมสำหรับวัตถุฐานข้อมูลส่วนใหญ่ (แน่นอนว่าเป็นตารางดัชนี ฯลฯ แต่ไม่ใช่ฐานข้อมูลผู้ใช้) อย่างไรก็ตามในทางปฏิบัติ DDL ใด ๆ จะได้รับการACCESS EXCLUSIVE
ล็อควัตถุเป้าหมายทำให้ไม่สามารถเข้าถึงได้อย่างสมบูรณ์จนกว่าธุรกรรม DDL จะเสร็จสิ้น นอกจากนี้ไม่ใช่ว่าทุกสถานการณ์จะได้รับการจัดการค่อนข้างดีตัวอย่างเช่นหากคุณพยายามเลือกจากตารางfoo
ในขณะที่ธุรกรรมอื่นกำลังทิ้งมันและสร้างตารางทดแทนfoo
ธุรกรรมที่ถูกบล็อกจะได้รับข้อผิดพลาดในที่สุดแทนที่จะค้นหาfoo
ตารางใหม่ (แก้ไข: สิ่งนี้ได้รับการแก้ไขในหรือก่อน PostgreSQL 9.3)
CREATE INDEX ... CONCURRENTLY
เป็นสิ่งพิเศษโดยใช้ธุรกรรมสามรายการเพื่อเพิ่มดัชนีลงในตารางในขณะที่อนุญาตให้อัปเดตพร้อมกันดังนั้นจึงไม่สามารถดำเนินการในธุรกรรมได้
นอกจากนี้ยังVACUUM
ไม่สามารถใช้คำสั่งการบำรุงรักษาฐานข้อมูลในธุรกรรม
foo
ในขณะที่ธุรกรรมอื่นกำลังทิ้งและสร้างขึ้นมาใหม่ฉันก็ตกลงกับเวอร์ชันเก่าหรือข้อผิดพลาด ฉันไม่เห็นด้วยกับเวอร์ชันใหม่เพราะยังไม่ได้ตกลงกันดังนั้นฉันจึงต้องไม่เห็น ฉันตกลงกับข้อผิดพลาดเนื่องจากในการเข้าถึงธุรกรรมพร้อมกันจะต้องมีการเตรียมเพื่อเริ่มการทำธุรกรรมใหม่อยู่ดี หากข้อผิดพลาดเกิดขึ้นบ่อยเกินความจำเป็นอาจทำให้ประสิทธิภาพลดลง แต่ก็ยังถูกต้อง
แม้ว่าจะไม่ได้พูดถึง "ย้อนกลับ" อย่างเคร่งครัด แต่ใน Oracle คำสั่ง FLASHBACK สามารถใช้เพื่อเลิกทำการเปลี่ยนแปลงประเภทนี้ได้หากฐานข้อมูลได้รับการกำหนดค่าให้รองรับ
ไม่สามารถทำได้ด้วยMySQLดูเหมือนว่าโง่มาก แต่จริง ... (ตามคำตอบที่ยอมรับ)
"คำสั่ง CREATE TABLE ใน InnoDB ถูกประมวลผลเป็นธุรกรรมเดียวซึ่งหมายความว่า ROLLBACK จากผู้ใช้จะไม่เลิกทำคำสั่ง CREATE TABLE ที่ผู้ใช้ทำระหว่างธุรกรรมนั้น"
https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
ลองหลายวิธีแล้วมันก็ไม่ย้อน ..
วิธีแก้ปัญหาคือเพียงตั้งค่าสถานะความล้มเหลวและทำ "drop table tblname" หากหนึ่งในแบบสอบถามล้มเหลว
ดูเหมือนคำตอบอื่น ๆ จะค่อนข้างล้าสมัย
ณ ปี 2019:
START TRANSACTION ... COMMIT;
คุณยังไม่สามารถย้อนกลับคำสั่ง DDL ในธุรกรรมได้หากคำสั่งหลังในธุรกรรมเดียวกันล้มเหลว (ดูหมายเหตุใน dev. mysql.com/doc/refman/8.0/th/… )