เป็นไปได้ไหมที่จะย้อนกลับคำสั่ง CREATE TABLE และ ALTER TABLE ในฐานข้อมูล SQL หลัก


110

ฉันกำลังทำงานกับโปรแกรมที่ออก DDL ฉันต้องการทราบว่าCREATE TABLEDDL ที่คล้ายกันนี้สามารถย้อนกลับได้หรือไม่

  • Postgres
  • MySQL
  • SQLite
  • และคณะ

อธิบายว่าแต่ละฐานข้อมูลจัดการธุรกรรมกับ DDL อย่างไร


เพียงเพื่อเสริมหัวข้อนี้H2ยังไม่สนับสนุนงบ DDL การทำธุรกรรมสำหรับส่วนมากของคำสั่ง SQL ตามนี้
Gabriel Paim

คำตอบ:


150

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysisให้ภาพรวมของปัญหานี้จากมุมมองของ PostgreSQL

การทำธุรกรรม DDL เป็นไปตามเอกสารนี้หรือไม่

  • PostgreSQL - ใช่
  • MySQL - ไม่; DDL ทำให้เกิดการคอมมิตโดยปริยาย
  • Oracle Database 11g Release 2 ขึ้นไป - โดยค่าเริ่มต้นไม่มี แต่มีทางเลือกอื่นที่เรียกว่าการกำหนดนิยามใหม่ตามรุ่น
  • Oracle เวอร์ชันเก่า - ไม่ DDL ทำให้เกิดการคอมมิตโดยปริยาย
  • SQL Server - ใช่
  • Sybase Adaptive Server - ใช่
  • DB2 - ใช่
  • Informix - ใช่
  • Firebird (Interbase) - ใช่

SQLite ดูเหมือนจะมี DDL แบบทรานแซคชันเช่นกัน ฉันสามารถROLLBACKสร้างCREATE TABLEคำสั่งใน SQLite ได้ ใช้CREATE TABLEเอกสารไม่ได้พูดถึงการทำธุรกรรมใด ๆ เป็นพิเศษ 'gotchas'


8
อย่างไรก็ตามโปรแกรมควบคุม Python เริ่มต้นสำหรับ sqlite จะป้องกัน SQL ที่ทำธุรกรรม bugs.python.org/issue10740
joeforker

ดังนั้นคำตอบคือ "ใช่สามารถย้อนกลับได้เว้นแต่คุณจะใช้ MySQL หรือ Oracle เวอร์ชันเก่ากว่า"
rjmunro

ไม่มีฐานข้อมูล SQL อื่นนอกเหนือจากที่ระบุไว้
joeforker

3
มีปัญหาเปิดใน MariaDB สำหรับการเพิ่มการสนับสนุนการทำธุรกรรม DDL คือjira.mariadb.org/browse/MDEV-4259 ช่วยโหวตให้หน่อย
Gili

1
ALTER TABLEคำสั่ง SQLite ที่ค่อนข้าง จำกัดยังสามารถย้อนกลับได้ มันไม่ได้เป็นที่กล่าวถึงอย่างชัดเจนในเอกสาร สิ่งที่กล่าวถึงคือวิธีดำเนินการเปลี่ยนแปลง "ขั้นสูง" ภายในธุรกรรม
Thomas

32

PostgreSQL มี DDL แบบธุรกรรมสำหรับวัตถุฐานข้อมูลส่วนใหญ่ (แน่นอนว่าเป็นตารางดัชนี ฯลฯ แต่ไม่ใช่ฐานข้อมูลผู้ใช้) อย่างไรก็ตามในทางปฏิบัติ DDL ใด ๆ จะได้รับการACCESS EXCLUSIVEล็อควัตถุเป้าหมายทำให้ไม่สามารถเข้าถึงได้อย่างสมบูรณ์จนกว่าธุรกรรม DDL จะเสร็จสิ้น นอกจากนี้ไม่ใช่ว่าทุกสถานการณ์จะได้รับการจัดการค่อนข้างดีตัวอย่างเช่นหากคุณพยายามเลือกจากตารางfooในขณะที่ธุรกรรมอื่นกำลังทิ้งมันและสร้างตารางทดแทนfooธุรกรรมที่ถูกบล็อกจะได้รับข้อผิดพลาดในที่สุดแทนที่จะค้นหาfooตารางใหม่ (แก้ไข: สิ่งนี้ได้รับการแก้ไขในหรือก่อน PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY เป็นสิ่งพิเศษโดยใช้ธุรกรรมสามรายการเพื่อเพิ่มดัชนีลงในตารางในขณะที่อนุญาตให้อัปเดตพร้อมกันดังนั้นจึงไม่สามารถดำเนินการในธุรกรรมได้

นอกจากนี้ยังVACUUMไม่สามารถใช้คำสั่งการบำรุงรักษาฐานข้อมูลในธุรกรรม


ฉันจะเถียงว่าถ้าฉันพยายามเลือกจากตารางfooในขณะที่ธุรกรรมอื่นกำลังทิ้งและสร้างขึ้นมาใหม่ฉันก็ตกลงกับเวอร์ชันเก่าหรือข้อผิดพลาด ฉันไม่เห็นด้วยกับเวอร์ชันใหม่เพราะยังไม่ได้ตกลงกันดังนั้นฉันจึงต้องไม่เห็น ฉันตกลงกับข้อผิดพลาดเนื่องจากในการเข้าถึงธุรกรรมพร้อมกันจะต้องมีการเตรียมเพื่อเริ่มการทำธุรกรรมใหม่อยู่ดี หากข้อผิดพลาดเกิดขึ้นบ่อยเกินความจำเป็นอาจทำให้ประสิทธิภาพลดลง แต่ก็ยังถูกต้อง
ม.ค. Hudec

1
@ JanHudec: คุณจะไม่เห็นตารางใหม่ในเวอร์ชันที่ไม่ถูกผูกมัดมีเพียงผลลัพธ์ของธุรกรรมทั้งหมดที่ทิ้ง / สร้างขึ้นใหม่ กล่าวคือการทำธุรกรรมที่ลดลงสร้างและสร้างตารางขึ้นใหม่คือกระบวนการที่มีประสิทธิภาพในการเขียนอะตอมอื่น ๆ ที่เลือกจากตารางนั้น (แต่ทุกอย่างจะถูกบล็อกทันทีที่พวกเขาพยายามอ่านสคีมาของตาราง)
araqnid

5

แม้ว่าจะไม่ได้พูดถึง "ย้อนกลับ" อย่างเคร่งครัด แต่ใน Oracle คำสั่ง FLASHBACK สามารถใช้เพื่อเลิกทำการเปลี่ยนแปลงประเภทนี้ได้หากฐานข้อมูลได้รับการกำหนดค่าให้รองรับ


5

ไม่สามารถทำได้ด้วยMySQLดูเหมือนว่าโง่มาก แต่จริง ... (ตามคำตอบที่ยอมรับ)

"คำสั่ง CREATE TABLE ใน InnoDB ถูกประมวลผลเป็นธุรกรรมเดียวซึ่งหมายความว่า ROLLBACK จากผู้ใช้จะไม่เลิกทำคำสั่ง CREATE TABLE ที่ผู้ใช้ทำระหว่างธุรกรรมนั้น"

https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html

ลองหลายวิธีแล้วมันก็ไม่ย้อน ..

วิธีแก้ปัญหาคือเพียงตั้งค่าสถานะความล้มเหลวและทำ "drop table tblname" หากหนึ่งในแบบสอบถามล้มเหลว


1
ประณาม. ฉันพยายามหาสาเหตุที่ตารางที่สร้างไว้ก่อนหน้านี้ไม่หายไปเมื่อตาราง (สร้าง) บางตารางล้มเหลวในชั่วโมงที่ผ่านมา ฉันใช้ MariaDB (XAMPP เปลี่ยนจาก MySQL เป็น MariaDB) แต่กรณีก็เหมือนกัน นี่มันโง่: |
akinuri

4

ดูเหมือนคำตอบอื่น ๆ จะค่อนข้างล้าสมัย

ณ ปี 2019:

  • Postgres รองรับ DDL แบบธุรกรรมสำหรับหลายรุ่น
  • SQLite รองรับ DDL แบบทรานแซกชันสำหรับหลายรุ่น
  • MySQL รองรับAtomic DDL ตั้งแต่ 8.0 (ซึ่งเปิดตัวในปี 2018)

2
ควรทราบว่า Atomic DDL ใน MySQL 8 หมายถึงคำสั่ง atomic DDL เท่านั้น แต่ไม่ใช่คำสั่งธุรกรรม คำสั่ง DDL ไม่ว่าจะเป็น atomic หรือไม่ก็ตามส่วนใหญ่ยังคงทำให้เกิดการกระทำโดยนัยดังนั้นจึงไม่สามารถดำเนินการภายในธุรกรรมอื่นได้ (เช่นSTART TRANSACTION ... COMMIT;คุณยังไม่สามารถย้อนกลับคำสั่ง DDL ในธุรกรรมได้หากคำสั่งหลังในธุรกรรมเดียวกันล้มเหลว (ดูหมายเหตุใน dev. mysql.com/doc/refman/8.0/th/… )
Lacek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.