Можно ли откатить операторы CREATE TABLE и ALTER TABLE в основных базах данных SQL?

108

Я работаю над программой, которая выдает DDL. Я хотел бы знать, CREATE TABLEможно ли откатить аналогичный DDL в

  • Postgres
  • MySQL
  • SQLite
  • и другие

Опишите, как каждая база данных обрабатывает транзакции с помощью DDL.

Joeforker
источник
Просто , чтобы дополнить эту нить, H2 также не поддерживает транзакционных операторы DDL для большинства команд SQL, в соответствии с этим .
Габриэль

Ответы:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis предоставляет обзор этой проблемы с точки зрения PostgreSQL.

Является ли DDL транзакционным согласно этому документу?

  • PostgreSQL - да
  • MySQL - нет; DDL вызывает неявную фиксацию
  • Oracle Database 11g Release 2 и выше - по умолчанию нет, но существует альтернатива, называемая переопределением на основе выпуска
  • Старые версии Oracle - нет; DDL вызывает неявную фиксацию
  • SQL Server - да
  • Sybase Adaptive Server - да
  • DB2 - да
  • Informix - да
  • Firebird (Interbase) - да

SQLite, похоже, также имеет транзакционный DDL. Я был в состоянии ROLLBACKс CREATE TABLEзаявлением в SQLite. В его CREATE TABLEдокументации не упоминаются какие-либо особые транзакционные "подводные камни".

Joeforker
источник
8
Однако драйвер Python по умолчанию для sqlite предотвращает транзакционный SQL. bugs.python.org/issue10740
joeforker
Итак, ответ: «Да, их можно откатить, если вы не используете MySQL или более старые версии Oracle».
rjmunro
Нет, кроме перечисленных, существуют и другие базы данных SQL.
joeforker
3
В MariaDB есть открытая проблема для добавления поддержки транзакционного DDL: jira.mariadb.org/browse/MDEV-4259 . Пожалуйста, проголосуйте за это.
Gili
1
Несколько ограниченный ALTER TABLEоператор SQLite также можно откатить. Это не упоминается явно в документации . Там упоминается, как выполнять «расширенные» изменения внутри транзакции.
Thomas
32

PostgreSQL имеет транзакционный DDL для большинства объектов баз данных (конечно, таблиц, индексов и т. Д., Но не баз данных, пользователей). Однако практически любой DDL получит ACCESS EXCLUSIVEблокировку целевого объекта, что сделает его полностью недоступным до завершения транзакции DDL. Кроме того, не все ситуации полностью обрабатываются - например, если вы попытаетесь выбрать из таблицы, в fooто время как другая транзакция отбрасывает ее и создает таблицу замены foo, тогда заблокированная транзакция, наконец, получит ошибку, а не найдет новую fooтаблицу. (Изменить: это было исправлено в PostgreSQL 9.3 или ранее)

CREATE INDEX ... CONCURRENTLY является исключительным, он использует три транзакции для добавления индекса в таблицу, позволяя одновременные обновления, поэтому сам по себе он не может быть выполнен в транзакции.

Также VACUUMв транзакции нельзя использовать команду обслуживания базы данных .

аракнид
источник
Я бы сказал, что если я попытаюсь выбрать из таблицы, fooпока другая транзакция отбрасывает и воссоздает ее, то у меня все в порядке со старой версией или ошибкой. Меня не устраивает новая версия, потому что она еще не зафиксирована, поэтому я не должен ее видеть. Я в порядке с ошибкой, потому что при одновременном доступе к транзакциям нужно быть готовым к перезапуску транзакций в любом случае. Если ошибки случаются чаще, чем необходимо, это может снизить производительность, но это все равно верно.
Ян Худек
1
@JanHudec: вы не увидите незафиксированную версию новой таблицы, только результат всей транзакции, которая сбросила / воссоздала ее. то есть транзакция, которая удаляет, воссоздает и повторно заполняет таблицу, является фактически атомарной по отношению к другим процессам, выбирающим из этой таблицы. (но все будет заблокировано, как только они попытаются прочитать схему таблицы)
araqnid
5

Хотя, строго говоря, это не «откат», в Oracle команду FLASHBACK можно использовать для отмены этих типов изменений, если база данных была настроена для ее поддержки.

Дэйв Коста
источник
5

Похоже, другие ответы устарели.

По состоянию на 2019 год:

  • Postgres поддерживает транзакционный DDL для многих выпусков.
  • SQLite поддерживает транзакционный DDL для многих выпусков.
  • MySQL поддерживает атомарный DDL с версии 8.0 (выпущенной в 2018 году).
PaulMest
источник
1
Следует отметить, что атомарный DDL в MySQL 8 относится только к атомарным операторам DDL, но не к операторам транзакций. Оператор DDL, атомарный или нет, в большинстве случаев по-прежнему вызывает неявную фиксацию и, следовательно, не может быть выполнен в рамках другой транзакции (например, START TRANSACTION ... COMMIT;вы по-прежнему не можете откатить операторы DDL в транзакции, если последний в той же транзакции не работает. (См. Примечание в разделе dev. mysql.com/doc/refman/8.0/en/... )
Lacek
4

Невозможно сделать с MySQL, кажется, очень глупо, но это правда ... (согласно принятому ответу)

«Оператор CREATE TABLE в InnoDB обрабатывается как единая транзакция. Это означает, что ROLLBACK от пользователя не отменяет операторы CREATE TABLE, сделанные пользователем во время этой транзакции».

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

Пробовал несколько разных способов и просто не откатывается ..

Чтобы решить эту проблему, просто установите флаг ошибки и выполните команду «drop table tblname», если один из запросов завершился неудачно.

Роберт Синклер
источник
1
Черт. Я пытался понять, почему ранее созданные таблицы не исчезают, когда конкретная (создать) таблица выходит из строя в течение последнего часа. Я использую MariaDB (XAMPP переключился с MySQL на MariaDB), но случай такой же. Это глупо: |
Акинури