Est-il possible d'annuler les instructions CREATE TABLE et ALTER TABLE dans les principales bases de données SQL?

108

Je travaille sur un programme qui émet du DDL. Je voudrais savoir si CREATE TABLEun DDL similaire peut être restauré

  • Postgres
  • MySQL
  • SQLite
  • et al

Décrivez comment chaque base de données gère les transactions avec DDL.

Joeforker
la source
Juste pour compléter ce thread, H2 ne prend pas non plus en charge les instructions DDL transactionnelles pour la plupart des commandes SQL, selon cela .
Gabriel Paim

Réponses:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis fournit un aperçu de ce problème du point de vue de PostgreSQL.

Le DDL est-il transactionnel selon ce document?

  • PostgreSQL - oui
  • MySQL - non; DDL provoque une validation implicite
  • Oracle Database 11g version 2 et supérieure - par défaut, non, mais il existe une alternative appelée redéfinition basée sur l'édition
  • Anciennes versions d'Oracle - non; DDL provoque une validation implicite
  • SQL Server - oui
  • Sybase Adaptive Server - oui
  • DB2 - oui
  • Informix - oui
  • Firebird (Interbase) - oui

SQLite semble également avoir un DDL transactionnel. J'ai pu faire ROLLBACKune CREATE TABLEdéclaration dans SQLite. Sa CREATE TABLEdocumentation ne mentionne aucun «piège» transactionnel spécial.

Joeforker
la source
8
Cependant, le pilote Python par défaut pour sqlite empêche le SQL transactionnel. bugs.python.org/issue10740
joeforker
La réponse est donc "Oui, ils peuvent être annulés, sauf si vous utilisez MySQL ou des versions antérieures d'Oracle."
rjmunro
Non, il existe d'autres bases de données SQL en plus de celles répertoriées.
joeforker
3
Il existe un problème ouvert dans MariaDB pour l'ajout du support DDL transactionnel: jira.mariadb.org/browse/MDEV-4259 . Veuillez voter pour cela.
Gili
1
L' ALTER TABLEinstruction quelque peu limitée de SQLite peut également être annulée. Il n'est pas explicitement mentionné dans la documentation . Ce qui est mentionné, c'est comment effectuer des changements "avancés" dans une transaction.
Thomas
32

PostgreSQL a un DDL transactionnel pour la plupart des objets de base de données (certainement les tables, les index, etc. mais pas les bases de données, les utilisateurs). Cependant, pratiquement n'importe quel DDL obtiendra un ACCESS EXCLUSIVEverrou sur l'objet cible, le rendant complètement inaccessible jusqu'à ce que la transaction DDL se termine. De plus, toutes les situations ne sont pas tout à fait gérées - par exemple, si vous essayez de sélectionner dans une table foopendant qu'une autre transaction la supprime et crée une table de remplacement foo, la transaction bloquée recevra finalement une erreur plutôt que de trouver la nouvelle footable. (Edit: cela a été corrigé dans ou avant PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY est exceptionnel, il utilise trois transactions pour ajouter un index à une table tout en autorisant les mises à jour simultanées, il ne peut donc pas être exécuté lui-même dans une transaction.

De plus, la commande de maintenance de la base de données VACUUMne peut pas être utilisée dans une transaction.

araqnid
la source
Je dirais que si j'essaie de sélectionner dans la table foopendant qu'une autre transaction est en train de la laisser tomber et de la recréer, alors je suis d'accord avec l'ancienne version ou l'erreur. Je ne suis pas d'accord avec la nouvelle version, car elle n'était pas encore validée, donc je ne dois pas la voir. Je suis d'accord avec une erreur, car dans l'accès transactionnel simultané, il faut être prêt à redémarrer les transactions de toute façon. Si les erreurs se produisent plus souvent que nécessaire, cela peut réduire les performances, mais cela reste correct.
Jan Hudec
1
@JanHudec: vous ne verrez pas une version non validée de la nouvelle table, seulement le résultat de la transaction entière qui l'a supprimée / recréée. c'est-à-dire qu'une transaction qui supprime, recrée et repeuple une table est effectivement atomique par rapport à d'autres processus sélectionnant dans cette table. (mais tout sera bloqué dès qu'ils essaieront même de lire le schéma de la table)
araqnid
5

Bien qu'il ne s'agisse pas à proprement parler d'une «restauration», dans Oracle, la commande FLASHBACK peut être utilisée pour annuler ces types de modifications, si la base de données a été configurée pour la prendre en charge.

Dave Costa
la source
5

On dirait que les autres réponses sont assez dépassées.

À partir de 2019:

  • Postgres a pris en charge le DDL transactionnel pour de nombreuses versions.
  • SQLite a pris en charge le DDL transactionnel pour de nombreuses versions.
  • MySQL prend en charge Atomic DDL depuis la version 8.0 (sortie en 2018).
PaulMest
la source
1
Il convient de noter que le DDL atomique dans MySQL 8 se réfère à de simples instructions DDL atomiques, mais pas à des instructions transactionnelles. Une instruction DDL, atomique ou non, provoque toujours une validation implicite et ne peut donc pas être exécutée dans une autre transaction (par exemple START TRANSACTION ... COMMIT;, vous ne pouvez toujours pas annuler les instructions DDL dans une transaction si celle-ci échoue dans la même transaction (voir note sous dev. mysql.com/doc/refman/8.0/en/… )
Lacek
4

On ne peut pas faire avec MySQL il semble, très stupide, mais vrai ... (selon la réponse acceptée)

"L'instruction CREATE TABLE dans InnoDB est traitée comme une seule transaction. Cela signifie qu'un ROLLBACK de l'utilisateur n'annule pas les instructions CREATE TABLE que l'utilisateur a faites pendant cette transaction."

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

J'ai essayé de différentes manières et cela ne reviendra tout simplement pas.

Pour contourner le problème, il vous suffit de définir un indicateur d’échec et de faire «drop table tblname» si l’une des requêtes a échoué.

Robert Sinclair
la source
1
Zut. J'ai essayé de comprendre pourquoi les tables précédemment créées ne disparaissent pas lorsqu'une table particulière (créer) échoue depuis une heure. J'utilise MariaDB (XAMPP est passé de MySQL à MariaDB), mais le cas est le même. C'est idiot: |
akinuri