Синхронизация одной Postgres базы данных в другую.

pgsync декларирует следующие преимущества

  • скорость - таблицы передаются параллельно
  • безопасность - встроенные методы, чтобы исключить утечку чувствительных данных
  • гибкость - изящная обработка различий в схемах данных, например отсутствующих колонок
  • удобство - синхронизация части таблиц, групп таблиц, и относящихся записей

Проверено в бою на Instcart.

Установка

gem install pgsync

в директории проекта

pgsync --init

будет создан файл .pgsync.yml, файл для настройки. Рекомендуется добавить файл под контроль версий. Сам файл не содержит чувствительной информации и может распространяться через контроль версий.

Использование

Синхронизировать все таблицы

pgsync

Синхронизировать конкретные таблицы

pgsync table1, table2

Синхронизировать конкретные строки

pgsync articles "where active = 1"

синхронизация строк с сохранением существующих

pgsync articles "where active = 1" --preserve

или очистка/удаление

pgsync articles "where active = 1" --truncate

Исключение таблиц

pgsync --exclude users

Для исключения таблиц на постоянной основе используем конфигурацию

exclude:
  - payments
  - users

Для Rails правильным будет добавить в исключения

exclude:
  - schema_migrations
  - ar_internal_metadata

Определение групп

groups:
  news:
  	- articles
    - tags
    - comments
    - links    

Синхронизация группы

pgsync news

Детальные настройки для каждой таблицы в группе и указание параметра при синхронизации

groups:
  news:
    artciles: "where id = {1}"
    comments: "where acrticle_id = {1} order by created_at desc limit 10"
    links: "where id in (select link_id from articles where id = {1})"

запуск

pgsync news:123 

Схема данных

pgsync создан для работы с данными, для синхронизации, обновления схемы надо использовать миграции.

предварительная синхронизация схемы

pgsync --schema-first
Внимание! Это удалит все существующие данные.

Для конкретных таблиц

pgsync table1,table2 --schema-first

и только схема

pgsync --schema-only
pgsync даже не пытается синхронизировать расширения Postgres

Исключения данных

Чтобы исключить утечку данных с сервера, например пароли, email адреса

data_rules:
  email: unique_email
  last_name: random_letter
  birthday: random_date
  user.auth_token:
    value: secret
  visit_counts:
    statement: "(RANDOM() * 10)::int"
  encrypted_*: null  

last_name затронет все колонки называемые last_name, users.last_name затронет только данные в таблице users. Поддерживается "шаблоны поиска" (wildcards), первое найденное правило будет применено

Опции

  • unique_email
  • unique_phone
  • unique_secret
  • random_letter
  • random_int
  • random_date
  • random_time
  • random_ip
  • value
  • statement
  • null
  • untouched

Правила начинающиеся с unique_ требуют, чтобы в таблице был первичный ключ. unique_phone также требует чтобы первичный ключ был числом.

Внешние ключи

Внешние ключи затрудняют синхронизацию данных. Три возможных варианта:

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

Определяем порядок синхронизации вручную, и используем ключ --jobs 1, чтобы синхронизировалась одна таблица за раз.

pgsync table1,table2,table3 --jobs 1

если таблицы имеют deferrable constariants, используем

pgsync --deferrable-constraints

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

pgsync --disable-integrity

Отключение триггеров

pgsync --disable-user-triggers

Добавление данных

Для супер-больших таблиц, или только добавления данных в таблицы, синхронизируем пакетами (sync batches)

pgsync large_table --in-batches

Защита

Всегда подключаться через SSH или VPN. Или использовать sslmode=verify-full.

Безопасность

Чтобы исключить случайное уничтожение или перезапись данных в production, точка назначения ограничена на localhost или 127.0.0.1 по умолчанию. Чтобы использовать другой хост, добавить to_safe: true в .pgsync.yml

Несколько баз данных

pgsync --init db2

что создаст .pgsync-db2.yml, и запуск с этой конфигурацией

pgsync --db db2