Postgres pg_dump удаляет базу данных в другом порядке каждый раз

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

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

1.) Создайте БД 2.) Измените БД 3.) Храните дамп базы данных БД (pg_dump)

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

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

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

Благодаря!

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

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

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

https://github.com/akaihola/pgtricks

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

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

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

 $ 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 файлы перед .sql обработкой нового дампа.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

См. КОПИРОВАНИЕ (9.5)