Czy można wycofać instrukcje CREATE TABLE i ALTER TABLE w głównych bazach danych SQL?

108

Pracuję nad programem, który wystawia DDL. Chciałbym wiedzieć, czy CREATE TABLEi podobne DDL można przywrócić

  • Postgres
  • MySQL
  • SQLite
  • et al

Opisz, jak każda baza danych obsługuje transakcje z DDL.

joeforker
źródło
Wystarczy uzupełnić ten wątek, H2 również nie obsługuje transakcyjnych DDL dla większości poleceń SQL, według tego .
Gabriel Paim

Odpowiedzi:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis zawiera przegląd tego problemu z perspektywy PostgreSQL.

Czy DDL ma charakter transakcyjny zgodnie z tym dokumentem?

  • PostgreSQL - tak
  • MySQL - nie; DDL powoduje niejawne zatwierdzenie
  • Oracle Database 11g Release 2 i nowsze - domyślnie nie, ale istnieje alternatywa zwana redefinicją opartą na edycji
  • Starsze wersje Oracle - nie; DDL powoduje niejawne zatwierdzenie
  • SQL Server - tak
  • Sybase Adaptive Server - tak
  • DB2 - tak
  • Informix - tak
  • Firebird (Interbase) - tak

Wydaje się, że SQLite ma również transakcyjny DDL. Udało mi ROLLBACKsię CREATE TABLEwypowiedzieć w SQLite. Jego CREATE TABLEdokumentacja nie wspomina o żadnych specjalnych „pułapkach” transakcyjnych.

joeforker
źródło
8
Jednak domyślny sterownik Pythona dla sqlite zapobiega transakcyjnym SQL. bugs.python.org/issue10740
joeforker
Tak więc odpowiedź brzmi: „Tak, można je wycofać, chyba że używasz MySQL lub starszych wersji Oracle”.
rjmunro
Nie, istnieją inne bazy danych SQL poza wymienionymi.
joeforker
3
W MariaDB istnieje otwarty problem dotyczący dodania obsługi transakcyjnego DDL: jira.mariadb.org/browse/MDEV-4259 . Proszę zagłosuj na to.
Gili,
1
Nieco ograniczoną ALTER TABLEinstrukcję SQLite można również wycofać. Nie jest to wyraźnie wymienione w dokumentacji . Wspomniano tam o tym, jak dokonywać „zaawansowanych” zmian wewnątrz transakcji.
Thomas,
32

PostgreSQL ma transakcyjny DDL dla większości obiektów bazy danych (z pewnością tabele, indeksy itp., Ale nie bazy danych, użytkownicy). Jednak praktycznie każdy DDL zostanie ACCESS EXCLUSIVEzablokowany na obiekcie docelowym, co sprawi, że będzie on całkowicie niedostępny do czasu zakończenia transakcji DDL. Ponadto nie wszystkie sytuacje są w pełni obsługiwane - na przykład, jeśli spróbujesz wybrać z tabeli, foopodczas gdy inna transakcja porzuca ją i tworzy tabelę zastępczą foo, zablokowana transakcja ostatecznie otrzyma błąd, zamiast znaleźć nową footabelę. (Edycja: zostało to naprawione w PostgreSQL 9.3 lub wcześniej)

CREATE INDEX ... CONCURRENTLY jest wyjątkowy, wykorzystuje trzy transakcje, aby dodać indeks do tabeli, jednocześnie zezwalając na jednoczesne aktualizacje, więc nie można go samodzielnie wykonać w transakcji.

W VACUUMtransakcji nie można również użyć komendy konserwacji bazy danych .

araqnid
źródło
Twierdzę, że jeśli spróbuję wybrać z tabeli, foopodczas gdy inna transakcja jest porzucana i odtwarzana, wtedy mam OK ze starą wersją lub błędem. Nie jest mi dobrze z nową wersją, ponieważ nie została jeszcze zatwierdzona, więc nie mogę jej zobaczyć. Nic mi nie jest z błędem, ponieważ przy jednoczesnym dostępie transakcyjnym i tak trzeba być przygotowanym na ponowne uruchomienie transakcji. Jeśli błędy występują częściej niż to konieczne, może to zmniejszyć wydajność, ale nadal jest poprawne.
Jan Hudec
1
@JanHudec: nie zobaczysz niezatwierdzonej wersji nowej tabeli, a jedynie wynik całej transakcji, która ją usunęła / odtworzyła. tj. transakcja, która upuszcza, odtwarza i ponownie zapełnia tabelę, jest w rzeczywistości niepodzielna względem innych procesów wybierających z tej tabeli. (ale wszystko zostanie zablokowane, gdy tylko spróbują odczytać schemat tabeli)
araqnid
5

Chociaż nie jest to ściśle mówiąc „wycofanie”, w Oracle polecenie FLASHBACK może być używane do cofania tego typu zmian, jeśli baza danych została skonfigurowana do jej obsługi.

Dave Costa
źródło
5

Wygląda na to, że inne odpowiedzi są dość nieaktualne.

Od 2019 r .:

  • Postgres obsługiwał transakcyjny DDL w wielu wersjach.
  • SQLite obsługuje transakcyjny DDL w wielu wersjach.
  • MySQL obsługuje Atomic DDL od wersji 8.0 (wydanej w 2018 roku).
PaulMest
źródło
1
Należy zauważyć, że Atomic DDL w MySQL 8 odnosi się tylko do atomowych instrukcji DDL, ale nie do instrukcji transakcyjnych. Instrukcja DDL, atomowa lub nie, w większości nadal powoduje niejawne zatwierdzenie i dlatego nie może być wykonana w ramach innej transakcji (np START TRANSACTION ... COMMIT;. Nadal nie można wycofać instrukcji DDL w transakcji, jeśli ostatnia w tej samej transakcji się nie powiedzie (patrz uwaga pod dev. mysql.com/doc/refman/8.0/en/... )
Lacek
4

Wydaje się, że nie można tego zrobić z MySQL , bardzo głupie, ale prawdziwe ... (zgodnie z zaakceptowaną odpowiedzią)

„Instrukcja CREATE TABLE w InnoDB jest przetwarzana jako pojedyncza transakcja. Oznacza to, że ROLLBACK użytkownika nie cofa instrukcji CREATE TABLE wykonanych przez użytkownika podczas tej transakcji.”

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

Wypróbowano na kilka różnych sposobów i po prostu się nie wycofa.

Aby obejść ten problem, wystarczy ustawić flagę błędu i wykonać „drop table tblname”, jeśli jedno z zapytań zakończyło się niepowodzeniem.

Robert Sinclair
źródło
1
Cholera. Próbowałem dowiedzieć się, dlaczego wcześniej utworzone tabele nie znikają, gdy określona (tworzona) tabela nie działa w ciągu ostatniej godziny. Używam MariaDB (XAMPP przełączył się z MySQL na MariaDB), ale sprawa jest taka sama. To jest głupie: |
akinuri