Kürzlich habe ich herausgefunden, dass MySQL kein Rollback von DDL wie "alter table" unterstützt ... Als ich an PostgreSQL gewöhnt war, fand ich das seltsam, aber ein Freund von mir sagte mir, dass selbst Oracle dies nicht zulässt. Gibt es technische Gründe für die Nichtunterstützung? Ist es einfach ein "uninteressantes" Feature für sie?
Bearbeiten: habe gerade diesen Vergleich gefunden . Es sieht so aus, als gäbe es viele DBMS, die transaktionales DDL unterstützen.
DROP
oder ein Rollback durchführenRENAME
?Antworten:
Der Grund, warum dies in PostgreSQL funktioniert, ist, dass die Systemkataloge reguläre Tabellen sind. Das Erstellen einer neuen Funktion erfordert beispielsweise nur das Einfügen einer Zeile in die
pg_proc
Tabelle, das Ändern des Standardwerts einer Spalte nur das Aktualisieren einer Zeile inpg_attrdef
usw. Da Tabellen sowieso transaktional sind, müssten Sie fast alles daran setzen, damit sie nicht so funktionieren. (Viele schmerzhafte Implementierungsdetails wurden hier weggelassen. ;-))Ich nehme an, ohne den Quellcode zu kennen, dass andere Datenbankmodule einige benutzerdefinierte interne Strukturen verwenden, um ihre Systemkataloginformationen darzustellen. Sie müssten also zusätzliche Anstrengungen unternehmen, um Transaktions-DDL zum Laufen zu bringen, und dies hat offensichtlich für sie keine Priorität.
Die Kehrseite davon ist, dass dies der Grund ist, warum Hauptversions-Upgrades von PostgreSQL so schmerzhaft sind. Andere Produkte können vermutlich ihre internen Metadatenstrukturen unter Berücksichtigung von Änderungen und Aktualisierungen entwerfen, sodass beim Upgrade auf eine neue Hauptversion keine Probleme auftreten. In PostgreSQL gibt es keine Möglichkeit, eine Systemkatalogtabelle so zu ändern, dass sie plötzlich wie eine neuere Version einer Systemkatalogtabelle aussieht, zumindest nicht, wenn das System online bleibt, da dies den Zugriff auf die Systemkataloge erfordern würde. Urgh.
quelle
Die meisten nicht? Schade.
Ich benutze hauptsächlich SQL Server und das tut es auch. Ich weiß, dass Oracle dies nicht tut, aber ich dachte, Oracle könnte eine Abweichung sein.
Ich bin mir ziemlich sicher, dass Sie in SQL Server mehrere DDL-Anweisungen in einer einzigen Transaktion ausführen können, obwohl ich auch der Meinung bin, dass es einige Einschränkungen gibt (die ich alle vergessen habe). Sie können die meisten Dinge erstellen, ändern oder löschen und sie zurücksetzen, wenn Sie möchten. Red-Gate SQL Compare (ein Tool, das ich liebe) nutzt dies aus.
Das Problem dabei ist, dass Ihr Transaktionsumfang ziemlich interessant wird. Wenn Sie die Systemkataloge in eine Aktualisierungstransaktion (DDL) einbeziehen, laufen Sie Gefahr, einige wirklich wichtige Sperren zu erhalten, und Sie können den Zugriff auf die Systemkataloge blockieren. Benutzer können nicht viel tun, wenn ihre Abfragen ihre Tabellen nicht in den Katalogen finden!
Alles in allem ist es jedoch praktisch, DDL in eine Transaktion mit mehreren Kontoauszügen einbeziehen zu können.
Sinnvollerweise kann der SQL Server-DDL-Befehl
TRUNCATE
auch ein Element einer Transaktion mit mehreren Anweisungen sein . Sie können eine Zieltabelle abschneiden (sehr schnell), sie erstellen und dann ein Commit ausführen, wenn Sie das Ergebnis mögen. Wenn etwas schief geht, rollbackst du und voila !, es ist, als hättest du den Tisch nie gestört. Der Protokollspeicherplatz wird ebenfalls minimiert. Ich nutze das ziemlich oft.quelle
TRUNCATE
könnte nicht zurückgerollt werden. Ich lag falsch.In SQL Server können wir DDL-Anweisungen zurücksetzen, es wird kein automatisches Festschreiben am Ende der Anweisung verwendet. In anderen DBMS weiß ich nicht, aber ich erinnere mich, dass man in Oracle nicht dasselbe machen kann. Ich glaube, es ist spezifisch für jedes DBMS, nicht sicher, was der SQL-Standard dazu sagen würde, aber ich bin sicher, dass kein Hersteller den Standard zu 100% implementiert.
Es gibt eine ähnliche Frage zu SO: Ist es möglich, mehrere DDL-Anweisungen innerhalb einer Transaktion (in SQL Server) auszuführen?
quelle
Oracle hat das Parsing von gemeinsam genutzten Abfragen, sodass eine SELECT * FROM-Tabelle_a, die von einer Sitzung ausgeführt wird, (normalerweise) mit der einer anderen Sitzung identisch ist. Das würde scheitern, wenn eine Sitzung zehn Spalten in der Tabelle und eine andere elf Spalten in der Tabelle vermutet.
quelle