Чи можливий відкат операторів 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.