É possível reverter as instruções CREATE TABLE e ALTER TABLE nos principais bancos de dados SQL?

108

Estou trabalhando em um programa que emite DDL. Eu gostaria de saber se CREATE TABLEum DDL semelhante pode ser revertido em

  • Postgres
  • MySQL
  • SQLite
  • et al

Descreva como cada banco de dados lida com transações com DDL.

joeforker
fonte
Apenas para complementar este segmento, H2 também não suporta instruções DDL transacionais para a maioria dos comandos SQL, de acordo com isso .
Gabriel Paim

Respostas:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis fornece uma visão geral desse problema da perspectiva do PostgreSQL.

O DDL é transacional de acordo com este documento?

  • PostgreSQL - sim
  • MySQL - não; DDL causa um commit implícito
  • Oracle Database 11g Release 2 e superior - por padrão, não, mas existe uma alternativa chamada redefinição baseada em edição
  • Versões mais antigas do Oracle - não; DDL causa um commit implícito
  • SQL Server - sim
  • Sybase Adaptive Server - sim
  • DB2 - sim
  • Informix - sim
  • Firebird (Interbase) - sim

SQLite também parece ter DDL transacional. Consegui ROLLBACKuma CREATE TABLEdeclaração no SQLite. Sua CREATE TABLEdocumentação não menciona nenhuma 'pegadinha' transacional especial.

joeforker
fonte
8
No entanto, o driver Python padrão para sqlite evita SQL transacional. bugs.python.org/issue10740
joeforker
Portanto, a resposta é "Sim, eles podem ser revertidos, a menos que você esteja usando MySQL ou versões anteriores do Oracle."
rjmunro
Não, existem outros bancos de dados SQL além dos listados.
joeforker
3
Há um problema aberto no MariaDB para adicionar suporte DDL transacional: jira.mariadb.org/browse/MDEV-4259 . Por favor, vote nele.
Gili
1
A ALTER TABLEinstrução um tanto limitada do SQLite também pode ser revertida. Não é mencionado explicitamente na documentação . O que é mencionado ali é como realizar mudanças "avançadas" dentro de uma transação.
Thomas
32

O PostgreSQL tem DDL transacional para a maioria dos objetos de banco de dados (certamente tabelas, índices etc, mas não bancos de dados, usuários). No entanto, praticamente qualquer DDL obterá um ACCESS EXCLUSIVEbloqueio no objeto de destino, tornando-o completamente inacessível até que a transação DDL seja concluída. Além disso, nem todas as situações são bem tratadas - por exemplo, se você tentar selecionar da tabela fooenquanto outra transação a está descartando e criando uma tabela de substituição foo, a transação bloqueada finalmente receberá um erro em vez de encontrar a nova footabela. (Editar: isso foi corrigido em ou antes do PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY é excepcional, ele usa três transações para adicionar um índice a uma tabela enquanto permite atualizações simultâneas, portanto, ele não pode ser executado em uma transação.

Além disso, o comando de manutenção do banco de dados VACUUMnão pode ser usado em uma transação.

araqnid
fonte
Eu diria que, se tento selecionar na tabela fooenquanto outra transação está sendo descartada e recriada, então aceito a versão antiga ou erro. Não estou bem com a nova versão, porque ela ainda não foi confirmada, então não devo vê-la. Estou OK com um erro, porque no acesso transacional simultâneo, é preciso estar preparado para reiniciar as transações de qualquer maneira. Se ocorrerem erros com mais frequência do que o necessário, isso pode reduzir o desempenho, mas ainda está correto.
Jan Hudec
1
@JanHudec: você não verá uma versão não confirmada da nova tabela, apenas o resultado de toda a transação que a descartou / recriou. ou seja, uma transação que elimina, recria e preenche novamente uma tabela é efetivamente atômica em relação a outros processos selecionados dessa tabela. (mas tudo será bloqueado assim que eles tentarem ler o esquema da tabela)
araqnid
5

Embora não seja propriamente um "rollback", no Oracle o comando FLASHBACK pode ser usado para desfazer esses tipos de alterações, se o banco de dados foi configurado para suportá-lo.

Dave Costa
fonte
5

Parece que as outras respostas estão bem desatualizadas.

Em 2019:

  • Postgres oferece suporte a DDL transacional para muitos lançamentos.
  • O SQLite oferece suporte a DDL transacional para muitas versões.
  • O MySQL oferece suporte ao Atomic DDL desde 8.0 (lançado em 2018).
PaulMest
fonte
1
Deve-se notar que o Atomic DDL no MySQL 8 se refere a instruções DDL meramente atômicas, mas não a instruções transacionais. Uma instrução DDL, atômica ou não, na maioria das vezes ainda causa commit implícito e, portanto, não pode ser executada dentro de outra transação (por exemplo START TRANSACTION ... COMMIT;. Portanto, você ainda não pode reverter instruções DDL em uma transação se a última na mesma transação falhar. (Consulte a nota sob dev. mysql.com/doc/refman/8.0/en/… )
Lacek
4

Não pode ser feito com MySQL ao que parece, muito idiota, mas é verdade ... (de acordo com a resposta aceita)

"A instrução CREATE TABLE no InnoDB é processada como uma única transação. Isso significa que um ROLLBACK do usuário não desfaz as instruções CREATE TABLE que o usuário fez durante aquela transação."

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

Tentei de algumas maneiras diferentes e simplesmente não vai desistir ..

A alternativa é simplesmente definir um sinalizador de falha e "descartar a tabela tblname" se uma das consultas falhar.

Robert Sinclair
fonte
1
Droga. Tenho tentado descobrir por que as tabelas criadas anteriormente não vão desaparecer quando uma tabela específica (criar) falha na última hora. Estou usando MariaDB (o XAMPP mudou de MySQL para MariaDB), mas o caso é o mesmo. Isso é bobo: |
akinuri