Почему некоторые СУБД не разрешают откат для определенных операторов DDL?


21

Недавно я обнаружил, что MySQL не поддерживает откат DDL, такой как «изменение таблицы» ... При использовании для PostgreSQL это показалось мне странным, но мой друг сказал мне, что даже Oracle не позволяет этого ... Есть ли технические причины не поддерживать его? Это просто "неинтересная" особенность для них?

Изменить: только что нашел это сравнение . Похоже , есть много DBMSes , которые делают поддержку транзакций DDL.


3
MySQL не позволяет DDL внутри транзакции. Перед выполнением операторов DDL он фиксирует текущую транзакцию (все текущие операторы DML внутри этой транзакции!) Без какого-либо предупреждения.
Фрэнк Хейкенс

Точно, довольно раздражает ИМО :)
Joril

Я лично удивлен, что Postgres позволяет это - ты можешь даже откатить назад DROPили RENAME?
Джо

1
До тех пор, пока вы не отбросите всю базу данных, да :) Смотрите ссылку, которую я только что добавил
Joril

Таким образом, только Oracle и MySQL не допускают DDL-операторов внутри транзакций. Эта функция действительно позволяет легко развернуть схему.
Мариан

Ответы:


19

Причина, по которой это работает в PostgreSQL, заключается в том, что системные каталоги представляют собой обычные таблицы. Так, например, создание новой функции просто требует вставки строки в pg_procтаблицу, изменение значения столбца по умолчанию просто требует обновления какой-либо строки в строке pg_attrdefи т. Д. Так как таблицы в любом случае являются транзакционными, вам почти придётся изо всех сил не делать так, чтобы это работало. (Много болезненных деталей реализации здесь опущено. ;-))

Я полагаю, не зная исходного кода, что другие движки баз данных используют некоторые собственные внутренние структуры для представления информации своего системного каталога. И поэтому им пришлось бы приложить дополнительные усилия, вероятно, много дополнительных усилий, чтобы заставить транзакционный DDL работать, и это, очевидно, не является для них приоритетом.

Обратная сторона этого заключается в том, что именно поэтому основные обновления PostgreSQL так болезненны. Другие продукты могут проектировать свои внутренние структуры метаданных с учетом изменений и обновлений, поэтому при обновлении до новой основной версии проблем не возникает. В PostgreSQL нет способа изменить таблицу системного каталога так, чтобы она внезапно выглядела как более новая версия таблицы системного каталога, по крайней мере, при сохранении системы в оперативном режиме, поскольку для этого потребуется доступ к системным каталогам. Urgh.


1
Что ж, я бы предпочел, чтобы моя БД находилась в согласованном состоянии все время, а не просто обновляла версию БД, но я думаю, что это вопрос мнения :) Спасибо за ваше объяснение!
Джорил

Это может объяснить проблему для некоторых баз данных, но системные каталоги являются обычными таблицами в Oracle.
Ли Риффель

10

Больше нет? Облом.

Я главным образом использую SQL Server, и это делает. Я знаю, что Oracle нет, но я думал, что Oracle может быть отклонением.

В SQL Server я вполне уверен, что вы можете запускать несколько операторов DDL в одной транзакции, хотя я также думаю, что есть несколько ограничений (о которых я все забыл). Вы можете создать, изменить или отбросить большинство вещей и откатить их, если хотите. Red-Gate SQL Compare (инструмент, который мне нравится) использует это преимущество.

Проблема заключается в том, что ваша область транзакции становится довольно интересной ... Когда вы включаете системные каталоги в транзакцию обновления (DDL), вы рискуете получить некоторые действительно важные блокировки и можете заблокировать доступ к системным каталогам. Пользователи не могут многое сделать, если их запросы не могут найти их таблицы в каталогах!

В целом, однако, удобно иметь возможность включать DDL в транзакции с несколькими операторами.

Более полезно то, что команда SQL Server DDL TRUNCATE также может быть элементом транзакции с несколькими операторами . Вы можете усечь целевую таблицу (очень быстро), построить ее, а затем сделать коммит, если вам нравится результат. Если что-то пойдет не так, вы откатываетесь и вуаля !, как будто вы никогда не мешали столу. Пространство журнала также минимизировано. Я пользуюсь этим довольно часто.


2
Вот ответ, который показывает пример связанного с транзакциями DDL в SQL Server. Кроме того, я всегда думал, что TRUNCATEне может быть отменен. Я был неправ.
Ник Чаммас

5

В SQL Server мы можем откатывать операторы DDL, он не использует автоматическую фиксацию в конце оператора. В других СУБД я не знаю, но я помню, что в Oracle нельзя делать то же самое. Я считаю, что это специфично для каждой СУБД, не уверен, что об этом скажет стандарт SQL, но я уверен, что ни один производитель не реализует этот стандарт на 100%.

Есть аналогичный вопрос о SO: возможно ли выполнить несколько операторов DDL внутри транзакции (в SQL Server)?


5

Oracle имеет общий анализ запросов, поэтому SELECT * FROM table_a, выполняемый одним сеансом, (обычно) такой же, как и в другом сеансе. Это сломалось бы, если бы в одном сеансе было десять столбцов в таблице, а в другом - одиннадцать.


Интересно, что вы сказали, что у меня была похожая проблема на днях, приложение должно было быть «горячим» для развертывания, но, изменяя структуру таблицы для новой версии, оно не могло перекомпилировать JDBC PreparedStatements, кроме перезапуска так за это!
Гай

2
Кроме того, версия 11gR2 представляет концепцию выпусков, чтобы помочь с горячими обновлениями. Эффективно существующие соединения используют одну редакцию (с пятью столбцами). Вы запускаете новую редакцию, добавляете столбец и запускаете несколько новых подключений, используя новую редакцию для новых сеансов. Как только все выдающиеся сессии закончены, старая редакция становится бесполезной, и все использует новую редакцию. Нет отката, но вы не добавляете новую активность в новую редакцию, пока она не заработает.
Гари
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.