Có thể khôi phục các câu lệnh CREATE TABLE và ALTER TABLE trong cơ sở dữ liệu SQL chính không?


108

Tôi đang làm việc trên một chương trình phát hành DDL. Tôi muốn biết liệu CREATE TABLEDDL và các DDL tương tự có thể được khôi phục lại

  • Postgres
  • MySQL
  • SQLite
  • et al

Mô tả cách mỗi cơ sở dữ liệu xử lý các giao dịch với DDL.


Chỉ để bổ sung cho luồng này, H2 cũng không hỗ trợ các câu lệnh DDL giao dịch cho hầu hết các lệnh SQL, theo điều này .
Gabriel Paim

Câu trả lời:


148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis cung cấp tổng quan về vấn đề này từ quan điểm của PostgreSQL.

DDL có được giao dịch theo tài liệu này không?

  • PostgreSQL - có
  • MySQL - không; DDL gây ra một cam kết ngầm
  • Cơ sở dữ liệu Oracle 11g Release 2 trở lên - theo mặc định, không, nhưng tồn tại một giải pháp thay thế được gọi là định nghĩa lại dựa trên ấn bản
  • Các phiên bản cũ hơn của Oracle - không; DDL gây ra một cam kết ngầm
  • SQL Server - có
  • Máy chủ thích ứng Sybase - có
  • DB2 - có
  • Informix - có
  • Firebird (Interbase) - vâng

SQLite dường như cũng có DDL giao dịch. Tôi đã có thể viết ROLLBACKmột CREATE TABLEcâu lệnh trong SQLite. CREATE TABLETài liệu của nó không đề cập đến bất kỳ 'gotchas' giao dịch đặc biệt nào.


8
Tuy nhiên, trình điều khiển Python mặc định cho sqlite ngăn SQL giao dịch. bug.python.org/issue10740
joeforker

Vì vậy, câu trả lời là "Có, chúng có thể được khôi phục lại, trừ khi bạn đang sử dụng MySQL hoặc các phiên bản cũ hơn của Oracle."
rjmunro

Không, có những cơ sở dữ liệu SQL khác ngoài những cơ sở dữ liệu được liệt kê.
joeforker

3
Có một vấn đề mở trong MariaDB khi thêm hỗ trợ DDL giao dịch: jira.mariadb.org/browse/MDEV-4259 . Hãy bình chọn cho nó.
Gili

1
Câu lệnh có phần hạn chế ALTER TABLEcủa SQLite cũng có thể được khôi phục lại. Nó không được đề cập rõ ràng trong tài liệu . Điều được đề cập ở đó là cách thực hiện các thay đổi "nâng cao" bên trong một giao dịch.
Thomas

32

PostgreSQL có DDL giao dịch cho hầu hết các đối tượng cơ sở dữ liệu (chắc chắn là bảng, chỉ số, v.v. nhưng không phải cơ sở dữ liệu, người dùng). Tuy nhiên trên thực tế, bất kỳ DDL nào cũng sẽ bị ACCESS EXCLUSIVEkhóa đối tượng đích, khiến nó hoàn toàn không thể truy cập được cho đến khi giao dịch DDL kết thúc. Ngoài ra, không phải tất cả các tình huống đều được xử lý hoàn hảo - ví dụ: nếu bạn cố gắng chọn từ bảng footrong khi một giao dịch khác đang bỏ nó và tạo một bảng thay thế foo, thì giao dịch bị chặn cuối cùng sẽ nhận được lỗi thay vì tìm thấy foobảng mới . (Chỉnh sửa: điều này đã được sửa trong hoặc trước PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY là đặc biệt, nó sử dụng ba giao dịch để thêm chỉ mục vào bảng trong khi cho phép cập nhật đồng thời, vì vậy bản thân nó không thể được thực hiện trong một giao dịch.

Ngoài ra, lệnh duy trì cơ sở dữ liệu VACUUMkhông thể được sử dụng trong một giao dịch.


Tôi lập luận rằng nếu tôi cố gắng chọn từ bảng footrong khi một giao dịch khác đang giảm và tạo lại nó, thì tôi đồng ý với phiên bản cũ hoặc lỗi. Tôi không hài lòng với phiên bản mới, bởi vì nó chưa được cam kết, vì vậy tôi phải không nhìn thấy nó. Tôi không sao với lỗi, vì dù sao thì trong truy cập giao dịch đồng thời, người ta vẫn phải chuẩn bị để bắt đầu lại giao dịch. Nếu lỗi xảy ra thường xuyên hơn mức cần thiết, nó có thể làm giảm hiệu suất, nhưng nó vẫn đúng.
Jan Hudec

1
@JanHudec: bạn sẽ không thấy phiên bản không cam kết của bảng mới, chỉ là kết quả của toàn bộ giao dịch đã bỏ / tạo lại nó. tức là một giao dịch làm rớt, tạo lại và tái tạo lại một bảng có hiệu quả là nguyên tử hóa các quy trình khác chọn từ bảng đó. (nhưng tất cả mọi thứ sẽ được chặn ngay khi họ thậm chí cố gắng đọc schema của bảng)
araqnid

5

Mặc dù không nói chính xác là "khôi phục", trong Oracle, lệnh FLASHBACK có thể được sử dụng để hoàn tác các loại thay đổi này, nếu cơ sở dữ liệu đã được cấu hình để hỗ trợ nó.


5

Có vẻ như các câu trả lời khác đã khá lỗi thời.

Kể từ năm 2019:

  • Postgres đã hỗ trợ DDL giao dịch cho nhiều bản phát hành.
  • SQLite đã hỗ trợ DDL giao dịch cho nhiều bản phát hành.
  • MySQL đã hỗ trợ Atomic DDL kể từ 8.0 (được phát hành vào năm 2018).

1
Cần lưu ý rằng Atomic DDL trong MySQL 8 đề cập đến các câu lệnh DDL nguyên tử đơn thuần, chứ không phải các câu lệnh giao dịch. Một câu lệnh DDL, nguyên tử hay không, hầu hết vẫn gây ra cam kết ngầm và do đó không thể được thực hiện trong một giao dịch khác (ví dụ: START TRANSACTION ... COMMIT;Vì vậy, bạn vẫn không thể khôi phục các câu lệnh DDL trong một giao dịch nếu câu lệnh sau trong cùng một giao dịch không thành công. (Xem lưu ý của nhà phát triển) . mysql.com/doc/refman/8.0/en/… )
Lacek

4

Có vẻ như không thể thực hiện được với MySQL , rất ngu ngốc, nhưng đúng ... (theo câu trả lời được chấp nhận)

"Câu lệnh CREATE TABLE trong InnoDB được xử lý như một giao dịch duy nhất. Điều này có nghĩa là ROLLBACK từ người dùng không hoàn tác câu lệnh CREATE TABLE mà người dùng đã thực hiện trong giao dịch đó."

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

Đã thử một số cách khác nhau và nó chỉ đơn giản là sẽ không quay trở lại ..

Công việc xung quanh chỉ đơn giản là đặt cờ báo lỗi và thực hiện "thả bảng tblname" nếu một trong các truy vấn không thành công ..


1
Chỉ trích. Tôi đang cố gắng tìm ra lý do tại sao các bảng đã tạo trước đó sẽ không giải nén khi một bảng (tạo) cụ thể bị lỗi trong giờ qua. Tôi đang sử dụng MariaDB (XAMPP đã chuyển từ MySQL sang MariaDB), nhưng trường hợp vẫn vậy. Thật là ngớ ngẩn: |
akinuri
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.