Ограничения на изменения схемы PostgreSQL внутри транзакций?

мой фон базы данных с Oracle, поэтому я был удивлен, обнаружив, что Postgres включает изменения схемы в транзакциях - если вы начинаете, создаете таблицу, а затем откат, таблица уходит. Он также работает для добавления и удаления столбцов. Очевидно, это очень мило.

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

может ли кто-нибудь дать мне несколько указателей на документы или обсуждения изменений транзакционной схемы в Postgres? (Мы используем 8.2.13, хотя мы будем модернизировать в не слишком отдаленном будущем.) Или просто некоторые детали о заявлении, которые не будут включены в транзакцию?

5 ответов


согласно quick grep on docs, эти команды не могут быть выполнены в транзакциях:

  • кластер
  • совершить подготовлен
  • создать базу данных
  • создать табличное пространство
  • удалить
  • drop database
  • падение табличного пространства
  • откат подготовлен
  • вакууме

  • nextval и setval операции над последовательностями никогда не откатываются.
  • REINDEX DATABASE
  • REINDEX SYSTEM

здесь статья о транзакционном DDL на PostgreSQL Wiki


начиная с версии 9.1 PosgreSQL, похоже, что операторы schema create действительно являются транзакционными.

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
(0 rows)

begin;
create schema foo;
rollback;

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
(0 rows)

begin;
create schema foo;
commit;

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
 foo     |       10 | NULL
(1 row)

два сеанса одновременно с запуском "CREATE TABLE" немного колоритны:

http://postgresql.1045698.n5.nabble.com/Errors-on-CREATE-TABLE-IF-NOT-EXISTS-td5659080.html

CREATE TABLE выполняет предварительную проверку на наличие конфликта имен существует. Если это так, он либо ошибается (обычно), либо выходит с уведомлением (в случае если не существует). Но есть условие гонки: конфликтующая транзакция может создать таблицу после того, как мы сделаем этот чек и прежде чем мы создадим его сами.

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

perl -MDBI -E 'fork; fork; $d=DBI->connect("dbi:Pg:dbname=$ENV{USER}");' \
 $d->do("CREATE TABLE a (b int)")'
DBD::Pg::db do failed: ERROR:
   duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DETAIL:  Key (typname, typnamespace)=(a, 2200) already exists. at -e line 1.

из руководства, 13.5 (Валютный Контроль: Предостережения):

некоторые команды DDL, в настоящее время только усечение и перезапись таблицы формы ALTER TABLE, не являются MVCC-безопасными. Это означает, что после усечение или перезапись коммитов, таблица будет казаться пустой параллельные транзакции, если они используют снимок, сделанный до Команда DDL совершена. Это будет проблемой только для транзакции это не имело доступа к таблице в вопрос перед командой DDL started [...]

относительно перезаписи таблицы ALTER TABLE упоминается в разделе

добавление столбца с предложением по умолчанию или изменение типа существующий столбец потребует, чтобы вся таблица [...] была переписанный. Как исключение при изменении типа существующего столбец, если предложение USING не изменяет содержимое столбца и старый тип бинарных приводимые на новый тип или - неограниченный домен над новым типом, перезапись таблицы не требуется [ ... ] добавление или удаление столбца system oid также требует перезаписи всего таблица.