Ist es möglich, die Anweisungen CREATE TABLE und ALTER TABLE in wichtigen SQL-Datenbanken zurückzusetzen?

108

Ich arbeite an einem Programm, das DDL ausgibt. Ich würde gerne wissen, ob CREATE TABLEund ähnliche DDL zurückgesetzt werden können

  • Postgres
  • MySQL
  • SQLite
  • et al

Beschreiben Sie, wie jede Datenbank Transaktionen mit DDL verarbeitet.

Joeforker
quelle
Genau diesen Thread zu ergänzen, H2 auch nicht transaktionale DDL - Anweisungen für die meisten SQL - Befehle unterstützt, nach dieser .
Gabriel Paim

Antworten:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis bietet einen Überblick über dieses Problem aus Sicht von PostgreSQL.

Ist DDL gemäß diesem Dokument transaktional?

  • PostgreSQL - ja
  • MySQL - nein; DDL verursacht ein implizites Commit
  • Oracle Database 11g Release 2 und höher - standardmäßig nein, aber es gibt eine Alternative namens Edition-basierte Neudefinition
  • Ältere Versionen von Oracle - nein; DDL verursacht ein implizites Commit
  • SQL Server - ja
  • Sybase Adaptive Server - ja
  • DB2 - ja
  • Informix - ja
  • Firebird (Interbase) - ja

SQLite scheint auch Transaktions-DDL zu haben. Ich konnte ROLLBACKeine CREATE TABLEAnweisung in SQLite. In der CREATE TABLEDokumentation werden keine speziellen Transaktions-Fallstricke erwähnt.

Joeforker
quelle
8
Der Standard-Python-Treiber für SQLite verhindert jedoch Transaktions-SQL. bugs.python.org/issue10740
Joeforker
Die Antwort lautet also "Ja, sie können zurückgesetzt werden, es sei denn, Sie verwenden MySQL oder ältere Versionen von Oracle."
rjmunro
Nein, neben den aufgelisteten gibt es noch andere SQL-Datenbanken.
Joeforker
3
In MariaDB gibt es ein offenes Problem für das Hinzufügen von Transaktions-DDL-Unterstützung: jira.mariadb.org/browse/MDEV-4259 . Bitte stimmen Sie dafür.
Gili
1
Die etwas eingeschränkte ALTER TABLEAnweisung von SQLite kann ebenfalls zurückgesetzt werden. Es wird in der Dokumentation nicht ausdrücklich erwähnt . Dort wird erwähnt, wie "erweiterte" Änderungen innerhalb einer Transaktion durchgeführt werden.
Thomas
32

PostgreSQL verfügt über Transaktions-DDL für die meisten Datenbankobjekte (sicherlich Tabellen, Indizes usw., jedoch keine Datenbanken, Benutzer). Praktisch jede DDL erhält jedoch eine ACCESS EXCLUSIVESperre für das Zielobjekt, sodass es bis zum Abschluss der DDL-Transaktion vollständig unzugänglich ist. Außerdem werden nicht alle Situationen ganz behandelt. Wenn Sie beispielsweise versuchen, aus einer Tabelle auszuwählen, foowährend eine andere Transaktion sie löscht und eine Ersatztabelle erstellt foo, erhält die blockierte Transaktion schließlich einen Fehler, anstatt die neue fooTabelle zu finden. (Bearbeiten: Dies wurde in oder vor PostgreSQL 9.3 behoben.)

CREATE INDEX ... CONCURRENTLY ist außergewöhnlich, es verwendet drei Transaktionen, um einer Tabelle einen Index hinzuzufügen und gleichzeitig gleichzeitige Aktualisierungen zuzulassen, sodass es selbst nicht in einer Transaktion ausgeführt werden kann.

Der Befehl zur Datenbankwartung VACUUMkann auch nicht in einer Transaktion verwendet werden.

araqnid
quelle
Ich würde argumentieren, wenn ich versuche, aus einer Tabelle auszuwählen, foowährend eine andere Transaktion gelöscht und neu erstellt wird, bin ich mit der alten Version oder dem Fehler einverstanden. Ich bin mit der neuen Version nicht einverstanden, da sie noch nicht festgeschrieben wurde, daher darf ich sie nicht sehen. Ich bin mit einem Fehler in Ordnung, da man beim gleichzeitigen Transaktionszugriff darauf vorbereitet sein muss, Transaktionen trotzdem neu zu starten. Wenn Fehler häufiger als nötig auftreten, kann dies die Leistung beeinträchtigen, ist aber dennoch korrekt.
Jan Hudec
1
@JanHudec: Sie sehen keine nicht festgeschriebene Version der neuen Tabelle, sondern nur das Ergebnis der gesamten Transaktion, die sie gelöscht / neu erstellt hat. Das heißt, eine Transaktion, die eine Tabelle löscht, neu erstellt und neu auffüllt, ist für andere Prozesse, die aus dieser Tabelle auswählen, effektiv atomar. (aber alles wird blockiert, sobald sie überhaupt versuchen, das Schema der Tabelle zu lesen)
araqnid
5

Während es sich streng genommen nicht um ein "Rollback" handelt, kann in Oracle der Befehl FLASHBACK verwendet werden, um diese Art von Änderungen rückgängig zu machen, wenn die Datenbank so konfiguriert wurde, dass sie dies unterstützt.

Dave Costa
quelle
5

Sieht aus wie die anderen Antworten ziemlich veraltet sind.

Stand 2019:

  • Postgres hat Transaktions-DDL für viele Releases unterstützt.
  • SQLite unterstützt Transaktions-DDL für viele Releases.
  • MySQL unterstützt Atomic DDL seit 8.0 (das 2018 veröffentlicht wurde).
PaulMest
quelle
1
Man sollte beachten, dass sich die Atomic DDL in MySQL 8 lediglich auf atomare DDL-Anweisungen bezieht, nicht jedoch auf Transaktionsanweisungen. Eine atomare oder nicht atomare DDL-Anweisung verursacht meistens immer noch ein implizites Festschreiben und kann daher nicht innerhalb einer anderen Transaktion ausgeführt werden (z START TRANSACTION ... COMMIT;. B. Sie können DDL-Anweisungen in einer Transaktion immer noch nicht zurücksetzen, wenn letztere in derselben Transaktion fehlschlägt (siehe Hinweis unter dev). mysql.com/doc/refman/8.0/en/… )
Lacek
4

Kann nicht mit MySQL gemacht werden, es scheint sehr dumm, aber wahr ... (gemäß der akzeptierten Antwort)

"Die Anweisung CREATE TABLE in InnoDB wird als einzelne Transaktion verarbeitet. Dies bedeutet, dass ein ROLLBACK des Benutzers die Anweisungen CREATE TABLE, die der Benutzer während dieser Transaktion gemacht hat, nicht rückgängig macht."

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

Versuchte ein paar verschiedene Möglichkeiten und es wird einfach nicht zurückrollen ..

Um dieses Problem zu umgehen, setzen Sie einfach ein Fehlerflag und führen Sie "drop table tblname" aus, wenn eine der Abfragen fehlgeschlagen ist.

Robert Sinclair
quelle
1
Verdammt. Ich habe versucht herauszufinden, warum die zuvor erstellten Tabellen nicht verschwinden, wenn eine bestimmte (Erstellungs-) Tabelle in der letzten Stunde fehlschlägt. Ich verwende MariaDB (XAMPP wurde von MySQL auf MariaDB umgestellt), aber der Fall ist der gleiche. Das ist albern: |
Akinuri