È possibile ripristinare le istruzioni CREATE TABLE e ALTER TABLE nei principali database SQL?


108

Sto lavorando a un programma che emette DDL. Vorrei sapere se è CREATE TABLEpossibile eseguire il rollback di un DDL simile

  • Postgres
  • MySQL
  • SQLite
  • et al

Descrivi come ogni database gestisce le transazioni con DDL.


Solo per completare questo thread, H2 non supporta le istruzioni DDL transazionali per la maggior parte dei comandi SQL, secondo questo .
Gabriel Paim

Risposte:


148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis fornisce una panoramica di questo problema dal punto di vista di PostgreSQL.

DDL è transazionale secondo questo documento?

  • PostgreSQL: sì
  • MySQL - no; DDL causa un commit implicito
  • Oracle Database 11g Release 2 e versioni successive: per impostazione predefinita no, ma esiste un'alternativa chiamata ridefinizione basata sull'edizione
  • Versioni precedenti di Oracle - no; DDL causa un commit implicito
  • SQL Server: sì
  • Sybase Adaptive Server - sì
  • DB2 - sì
  • Informix - sì
  • Firebird (Interbase) - sì

Anche SQLite sembra avere un DDL transazionale. Sono stato in grado di ROLLBACKuna CREATE TABLEdichiarazione in SQLite. La sua CREATE TABLEdocumentazione non menziona alcun "trucco" transazionale speciale.


8
Tuttavia, il driver Python predefinito per sqlite impedisce l'SQL transazionale. bugs.python.org/issue10740
joeforker

Quindi la risposta è "Sì, possono essere ripristinati, a meno che non si utilizzi MySQL o versioni precedenti di Oracle".
rjmunro

No, ci sono altri database SQL oltre a quelli elencati.
joeforker

3
C'è un problema aperto in MariaDB per l'aggiunta del supporto DDL transazionale: jira.mariadb.org/browse/MDEV-4259 . Per favore votalo.
Gili

1
ALTER TABLEÈ anche possibile annullare l'istruzione un po 'limitata di SQLite. Non è esplicitamente menzionato nella documentazione . Ciò che è menzionato c'è come eseguire modifiche "avanzate" all'interno di una transazione.
Thomas

32

PostgreSQL ha DDL transazionale per la maggior parte degli oggetti di database (certamente tabelle, indici, ecc. Ma non database, utenti). Tuttavia, praticamente qualsiasi DDL otterrà un ACCESS EXCLUSIVEblocco sull'oggetto di destinazione, rendendolo completamente inaccessibile fino al termine della transazione DDL. Inoltre, non tutte le situazioni sono gestite del tutto, ad esempio, se provi a selezionare dalla tabella foomentre un'altra transazione la rilascia e crea una tabella sostitutiva foo, la transazione bloccata riceverà finalmente un errore anziché trovare la nuova footabella. (Modifica: questo problema è stato risolto in o prima di PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY è eccezionale, utilizza tre transazioni per aggiungere un indice a una tabella consentendo al contempo aggiornamenti simultanei, quindi non può essere eseguito da solo in una transazione.

Inoltre, il comando di manutenzione del database VACUUMnon può essere utilizzato in una transazione.


Direi che se provo a selezionare dalla tabella foomentre un'altra transazione viene rilasciata e ricreata, allora ottengo un OK con la vecchia versione o errore. Non sto bene con la nuova versione, perché non è stata ancora impegnata, quindi non devo vederla. Sto bene con un errore, perché in un accesso transazionale simultaneo bisogna essere preparati a riavviare comunque le transazioni. Se gli errori si verificano più spesso del necessario, potrebbe ridurre le prestazioni, ma è comunque corretto.
Jan Hudec

1
@ JanHudec: non vedrai una versione non salvata della nuova tabella, solo il risultato dell'intera transazione che l'ha rilasciata / ricreata. cioè una transazione che elimina, ricrea e ripopola una tabella è effettivamente atomica rispetto ad altri processi che selezionano da quella tabella. (ma tutto verrà bloccato non appena tenteranno di leggere lo schema della tabella)
araqnid

5

Sebbene non sia strettamente parlando un "rollback", in Oracle il comando FLASHBACK può essere utilizzato per annullare questi tipi di modifiche, se il database è stato configurato per supportarlo.


5

Sembra che le altre risposte siano piuttosto obsolete.

A partire dal 2019:

  • Postgres ha supportato DDL transazionale per molte versioni.
  • SQLite ha supportato DDL transazionale per molte versioni.
  • MySQL supporta Atomic DDL dalla 8.0 (che è stata rilasciata nel 2018).

1
Si dovrebbe notare che Atomic DDL in MySQL 8 si riferisce a istruzioni DDL semplicemente atomiche, ma non a dichiarazioni transazionali. Un'istruzione DDL, atomica o meno, per lo più causa ancora un commit implicito e quindi non può essere eseguita all'interno di un'altra transazione (ad esempio, START TRANSACTION ... COMMIT;quindi non è ancora possibile ripristinare le istruzioni DDL in una transazione se quest'ultima nella stessa transazione fallisce (vedere la nota sotto dev. mysql.com/doc/refman/8.0/en/… )
Lacek

4

Non può essere fatto con MySQL sembra, molto stupido, ma vero ... (come da risposta accettata)

"L'istruzione CREATE TABLE in InnoDB viene elaborata come una singola transazione. Ciò significa che un ROLLBACK da parte dell'utente non annulla le istruzioni CREATE TABLE effettuate dall'utente durante quella transazione."

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

Ho provato diversi modi e semplicemente non tornerà indietro.

La soluzione consiste nell'impostare semplicemente un flag di errore ed eseguire "drop table tblname" se una delle query fallisce.


1
Dannazione. Ho cercato di capire perché le tabelle create in precedenza non scompaiono quando una determinata tabella (crea) fallisce nell'ultima ora. Sto usando MariaDB (XAMPP è passato da MySQL a MariaDB), ma il caso è lo stesso. Questo è sciocco: |
akinuri
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.