Чи можливий відкат операторів CREATE TABLE та ALTER TABLE в основних базах даних SQL?


108

Я працюю над програмою, яка видає DDL. Мені хотілося б знати, чи можна CREATE TABLEподібний DDL повернути назад

  • Постгрес
  • MySQL
  • SQLite
  • та ін

Опишіть, як кожна база даних обробляє транзакції з DDL.


Просто для доповнення цього потоку, H2 також не підтримує транзакційні оператори DDL для більшості команд SQL відповідно до цього .
— Габріель Паїм

Відповіді:


148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis надає огляд цієї проблеми з точки зору PostgreSQL.

Чи відповідає транзакція DDL згідно з цим документом?

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

SQLite також має транзакційний DDL. Мені вдалося ROLLBACKзробити CREATE TABLEзаяву в SQLite. Його CREATE TABLEдокументація не кажучи вже про будь - яких спеціальних транзакційних «підводних каменів».


8
Однак драйвер Python за замовчуванням для sqlite запобігає транзакційному SQL. bugs.python.org/issue10740
— joeforker

Отже, відповідь - "Так, їх можна повернути назад, якщо ви не використовуєте MySQL або старіші версії Oracle".
— rjmunro

Ні, є інші бази даних SQL, крім перерахованих.
— joeforker

3
У MariaDB існує відкрите питання щодо додавання транзакційної підтримки DDL: jira.mariadb.org/browse/MDEV-4259 . Будь ласка, проголосуйте за це.
— Гілі

1
Дещо обмежена ALTER TABLEзаява SQLite також може бути відхилена назад. Це прямо не зазначено в документації . Там згадується, як здійснити "розширені" зміни всередині транзакції.
— Томас

32

PostgreSQL має транзакційний DDL для більшості об'єктів бази даних (звичайно, таблиці, індекси тощо, але не бази даних, користувачі). Однак практично будь-який DDL отримає ACCESS EXCLUSIVEблокування на цільовому об'єкті, що зробить його повністю недоступним до завершення транзакції DDL. Крім того, не всі ситуації цілком обробляються - наприклад, якщо ви намагаєтесь вибрати з таблиці, fooколи інша транзакція скидає її та створює таблицю заміни foo, тоді заблокована транзакція нарешті отримає помилку, а не знаходить нову fooтаблицю. (Редагувати: це було виправлено в або раніше PostgreSQL 9.3)

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

Також команда обслуговування бази даних VACUUMне може використовуватися для транзакції.


Я б стверджував, що якщо я спробую вибрати з таблиці, fooколи інша транзакція скидає та відтворює її, то я добре зі старою версією або помилкою. З новою версією я не в порядку, тому що вона ще не була зроблена, тому я не повинен її бачити. Я все в порядку з помилкою, тому що при одночасному транзакційному доступі потрібно бути готовим до перезапуску транзакцій у будь-якому випадку. Якщо помилки трапляються частіше, ніж потрібно, це може знизити продуктивність, але це все-таки правильно.
— Ян Худек

1
@JanHudec: ви не побачите незапущеної версії нової таблиці, лише результат усієї транзакції, яка її відкинула / відтворила. тобто транзакція, яка викидає, відтворює та повторно популяризує таблицю, є ефективно атомним wrt іншими процесами, що вибираються з цієї таблиці. (але все заблокується, як тільки вони спробують прочитати схему таблиці)
— araqnid

5

Хоча це не суворо кажучи про "відкат", в Oracle команда FLASHBACK може використовуватися для скасування цих типів змін, якщо база даних налаштована для її підтримки.


5

Схоже, інші відповіді досить застаріли.

Станом на 2019 рік:

  • Postgres підтримує транзакційний DDL для багатьох випусків.
  • SQLite підтримує транзакційний DDL для багатьох випусків.
  • MySQL підтримує Atomic DDL з 8.0 (який вийшов у 2018 році).

1
Слід зазначити, що Atomic DDL в MySQL 8 посилається лише на атомні оператори DDL, але не на транзакційні оператори. Заява DDL, атомна чи ні, здебільшого все ще викликає неявну фіксацію, і тому не може бути виконана в рамках іншої транзакції (наприклад, START TRANSACTION ... COMMIT;тому ви все ще не можете повернути оператори DDL в транзакції, якщо останній в тій же транзакції виходить з ладу. (Див. Примітку під розд. mysql.com/doc/refman/8.0/en/… )
— Lacek

4

Неможливо зробити це з MySQL, здається, дуже німим, але правдою ... (відповідно до прийнятої відповіді)

"Оператор CREATE TABLE в InnoDB обробляється як одна операція. Це означає, що ROLLBACK від користувача не скасовує CREATE TABLE заяви, які користувач робив під час цієї транзакції."

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

Спробував декілька різних способів, і він просто не відкатиться ..

Якщо вам не вдалося один із запитів, просто встановіть прапор відмови та зробіть "скидання tblname таблиці".


1
Блін. Я намагався з’ясувати, чому раніше створені таблиці не зникнуть, коли певна (створена) таблиця не працює протягом минулої години. Я використовую MariaDB (XAMPP перейшов з MySQL на MariaDB), але випадок той самий. Це нерозумно: |
— akinuri
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.