Postgres pg_dump каждый раз сбрасывает базу данных в другом порядке - PullRequest
17 голосов
/ 01 февраля 2010

Я пишу сценарий PHP (который также использует команды linux bash), который будет проходить через контрольные примеры, выполняя следующие действия:

Я использую базу данных PostgreSQL (8.4.2) ...

1.) Создать БД 2.) Модифицировать БД 3.) Сохранить дамп базы данных БД (pg_dump)

4.) Выполните регрессионное тестирование, выполнив шаги 1.) и 2.), а затем возьмите другой дамп базы данных и сравните его (diff) с исходным дампом базы данных из шага № 3.)

Однако я обнаружил, что pg_dump не всегда будет выгружать базу данных одним и тем же способом. Это будет сбрасывать вещи в другом порядке каждый раз. Поэтому, когда я выполняю diff для двух дампов базы данных, сравнение приведет к тому, что два файла будут разными, если они фактически одинаковы, просто в другом порядке.

Есть ли другой способ сделать pg_dump?

Спасибо!

Ответы [ 7 ]

14 голосов
/ 22 апреля 2010

Вот удобный скрипт для предварительной обработки pg_dump вывода, чтобы сделать его более подходящим для различий и хранения в управлении версиями:

https://github.com/akaihola/pgtricks

pg_dump_splitsort.py разбивает дамп на следующие файлы:

  • 0000_prologue.sql: все до первой КОПИИ
  • 0001_<schema>.<table>.sql
    .
    .
    NNNN_<schema>.<table>.sql: данные для каждой таблицы , отсортированные по первому полю
  • 9999_epilogue.sql: все после последней КОПИИ

Файлы данных таблицы нумеруются, поэтому для повторного создания базы данных можно использовать простую отсортированную конкатенацию всех файлов:

$ cat *.sql | psql <database>

Я обнаружил, что хороший способ быстро взглянуть на различия между дампами - это использовать инструмент meld для всего каталога:

$ meld old-dump/ new-dump/

Хранение дампа в управлении версиями также дает приличное представление о различиях. Вот как настроить git для использования цвета в diffs:

# ~/.gitconfig
[color]
        diff = true
[color "diff"]
        frag = white blue bold
        meta = white green bold
        commit = white red bold

Примечание: Если вы создали / удалили / переименовали таблицы, не забудьте удалить все .sql файлы перед последующей обработкой нового дампа.

11 голосов
/ 01 февраля 2010

Здесь стоит различать схему и данные. Схема выводится в довольно детерминированном порядке, большинство объектов в алфавитном порядке, ограничено межобъектными зависимостями. В некоторых ограниченных случаях порядок не полностью ограничен и может показаться случайным для стороннего наблюдателя, но это может быть исправлено в следующей версии.

Данные с другой стороны сбрасываются в порядке диска. Обычно это то, что вам нужно, потому что вы хотите, чтобы дампы были быстрыми, а не использовали безумные ресурсы для сортировки. Возможно, вы заметили, что когда вы «модифицируете БД», вы делаете ОБНОВЛЕНИЕ, которое фактически удаляет старое значение и добавляет новое значение в конце. И это, конечно, расстроит вашу стратегию сравнения.

Инструмент, который больше подходит для вашей цели: pg_comparator .

9 голосов
/ 01 февраля 2010

Невозможно заставить pg_dump создавать дамп данных в любом конкретном порядке, поскольку он создает дамп данных в порядке дисков - в этом случае это происходит намного быстрее.

Вы можете использовать опции "-a -d" для pg_dump и затем "сортировать" вывод, но новые строки в данных сделают отсортированный вывод непригодным для использования. Но для базового сравнения, изменилось ли что-нибудь, этого было бы достаточно.

3 голосов
/ 10 августа 2010

По состоянию на май 2010 года существует патч для pg_dump , который может быть полезен всем, кто интересуется этим вопросом - он добавляет опцию "--ordered" к этой утилите:

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

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

Я не проверял, но, думаю, стоит попробовать.

2 голосов
/ 01 февраля 2010

Если вас просто интересует схема:

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

-s, --schema-only           dump only the schema, no data
-t, --table=TABLE           dump the named table(s) only

Чтобы сгенерировать список таблиц для подачи выше, запрос information_schema.tables.

1 голос
/ 01 февраля 2010

Нередко PostgreSQL ведет себя недетерминированно - может быть, процессы реорганизации, запускаемые таймером, или что-то подобное происходит в фоновом режиме. Кроме того, я не знаю, как заставить pg_dump воспроизводить идентичные по битам выходные данные при последовательных запусках.

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

0 голосов
/ 19 июля 2017

Если производительность менее важна, чем заказ, который вы можете использовать:

COPY (select * from your_table order by some_col) to stdout
      with csv header delimiter ',';

См. КОПИЯ (9,5)

...