¿Es posible revertir las declaraciones CREATE TABLE y ALTER TABLE en las principales bases de datos SQL?

108

Estoy trabajando en un programa que emite DDL. Me gustaría saber si CREATE TABLEun DDL similar se puede revertir

  • Postgres
  • MySQL
  • SQLite
  • et al

Describe cómo cada base de datos maneja las transacciones con DDL.

joeforker
fuente
Solo para complementar este hilo, H2 tampoco admite declaraciones DDL transaccionales para la mayoría de los comandos SQL, según esto .
Gabriel Paim

Respuestas:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis proporciona una descripción general de este problema desde la perspectiva de PostgreSQL.

¿Es DDL transaccional de acuerdo con este documento?

  • PostgreSQL - sí
  • MySQL: no; DDL provoca una confirmación implícita
  • Oracle Database 11g Release 2 y superior: de forma predeterminada, no, pero existe una alternativa llamada redefinición basada en la edición
  • Versiones anteriores de Oracle: no; DDL provoca una confirmación implícita
  • SQL Server - sí
  • Sybase Adaptive Server: sí
  • DB2 - sí
  • Informix - sí
  • Firebird (Interbase) - sí

SQLite también parece tener DDL transaccional. Pude hacer ROLLBACKuna CREATE TABLEdeclaración en SQLite. Su CREATE TABLEdocumentación no menciona ningún error transaccional especial.

joeforker
fuente
8
Sin embargo, el controlador Python predeterminado para sqlite evita el SQL transaccional. bugs.python.org/issue10740
joeforker
Entonces, la respuesta es "Sí, se pueden revertir, a menos que esté utilizando MySQL o versiones anteriores de Oracle".
rjmunro
No, existen otras bases de datos SQL además de las enumeradas.
joeforker
3
Hay un problema abierto en MariaDB para agregar soporte DDL transaccional: jira.mariadb.org/browse/MDEV-4259 . Por favor vote por ello.
Gili
1
La ALTER TABLEdeclaración algo limitada de SQLite también se puede revertir. No se menciona explícitamente en la documentación . Lo que se menciona allí es cómo realizar cambios "avanzados" dentro de una transacción.
Thomas
32

PostgreSQL tiene DDL transaccional para la mayoría de los objetos de base de datos (ciertamente tablas, índices, etc. pero no bases de datos, usuarios). Sin embargo, prácticamente cualquier DDL obtendrá un ACCESS EXCLUSIVEbloqueo en el objeto de destino, haciéndolo completamente inaccesible hasta que finalice la transacción DDL. Además, no todas las situaciones se manejan del todo; por ejemplo, si intenta seleccionar de la tabla foomientras otra transacción la elimina y crea una tabla de reemplazo foo, la transacción bloqueada finalmente recibirá un error en lugar de encontrar la nueva footabla. (Editar: esto se solucionó en o antes de PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY es excepcional, utiliza tres transacciones para agregar un índice a una tabla mientras permite actualizaciones simultáneas, por lo que no se puede realizar en una transacción.

Además, el comando de mantenimiento de la base de datos VACUUMno se puede utilizar en una transacción.

arácnido
fuente
Yo diría que si trato de seleccionar de la tabla foomientras otra transacción se cae y la recrea, entonces estoy de acuerdo con la versión anterior o el error. No estoy de acuerdo con la nueva versión, porque aún no se ha confirmado, por lo que no debo verla. Estoy de acuerdo con un error, porque en el acceso transaccional concurrente uno debe estar preparado para reiniciar las transacciones de todos modos. Si los errores ocurren con más frecuencia de la necesaria, puede reducir el rendimiento, pero sigue siendo correcto.
Jan Hudec
1
@JanHudec: no verá una versión no confirmada de la nueva tabla, solo el resultado de toda la transacción que la eliminó / recreó. es decir, una transacción que elimina, recrea y vuelve a llenar una tabla es efectivamente atómica con respecto a otros procesos que se seleccionan de esa tabla. (pero todo se bloqueará tan pronto como intenten leer el esquema de la tabla)
araqnid
5

Si bien no es estrictamente una "reversión", en Oracle el comando FLASHBACK se puede utilizar para deshacer este tipo de cambios, si la base de datos se ha configurado para admitirlo.

Dave Costa
fuente
5

Parece que las otras respuestas están bastante desactualizadas.

A partir de 2019:

  • Postgres ha admitido DDL transaccional para muchas versiones.
  • SQLite ha admitido DDL transaccional para muchas versiones.
  • MySQL es compatible con Atomic DDL desde 8.0 (que se lanzó en 2018).
PaulMest
fuente
1
Cabe señalar que Atomic DDL en MySQL 8 se refiere simplemente a declaraciones DDL atómicas, pero no a declaraciones transaccionales. Una declaración DDL, atómica o no, en su mayoría todavía causa un compromiso implícito y, por lo tanto, no se puede ejecutar dentro de otra transacción (por ejemplo, por START TRANSACTION ... COMMIT;lo que aún no puede revertir las declaraciones DDL en una transacción si falla la última en la misma transacción (consulte la nota en dev. mysql.com/doc/refman/8.0/en/… )
Lacek
4

No se puede hacer con MySQL , parece, muy tonto, pero cierto ... (según la respuesta aceptada)

"La instrucción CREATE TABLE en InnoDB se procesa como una sola transacción. Esto significa que un ROLLBACK del usuario no deshace las declaraciones CREATE TABLE que el usuario hizo durante esa transacción".

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

Probé de diferentes maneras y simplemente no se revertirá.

La solución es simplemente establecer una marca de falla y hacer "eliminar tabla tblname" si una de las consultas falla.

Robert Sinclair
fuente
1
Maldición. He estado tratando de averiguar por qué las tablas creadas anteriormente no desaparecerán cuando una tabla en particular (crear) falla durante la última hora. Estoy usando MariaDB (XAMPP cambió de MySQL a MariaDB), pero el caso es el mismo. Esto es una tontería: |
akinuri