- PVSM.RU - https://www.pvsm.ru -
Для работы бывает полезно иметь несколько копий одной реальной базы для экспериментов, фикстур или просто тестовых приложений. База растет и время копирования через разворачивание дампа или с помощью шаблона также возрастает до утомительных величин. Для решения этого кейса уже описаны варианты использования файловой системы с поддержкой CoW - Btrfs [1]. В интернете находил такие инструкции [2], они сводятся к тому, что делается снепшот всего сервера. И для работы второго "скопированного" нужно перегенерировать pid и сменить порт для предотвращения конфликтов. Этот способ довольно универсальный относительно конфигурации баз на сервере, но кажется имеет ограничение для неопределенного кол-ва параллельных снепшотов серверов.
В этой статье предлагаю свой вариант реализации снепшотов на одном экземпляре сервера postgres и одной базы, на произвольное кол-во копий.
Инструкция linux only, про поддержку CoW файловых систем на Windows не в курсе.
Это может быть отдельное устройство (подключенное аппаратно либо в менеджере виртуальных устройств)
Это может быть чистый раздел на текущем устройстве (настроить разделы via cfdisk)
Это даже может быть loop device на основе файла (См. losetup)
# Пусть устройство называется
/dev/sdb
2. Отформатируем устройство в Btrfs.
sudo apt-get update && apt-get install -y btrfs-progs
sudo mkfs.btrfs -L btrfs_disk /dev/sdb
3. Примонтируем устройство в систему.
# Для примера возьмем каталог /mnt/btrfs
sudo mkdir -p /mnt/btrfs && sudo mount /dev/sdb /mnt/btrfs
- (Optional) Можно сделать отдельный каталог только для tablespace.
sudo mkdir /mnt/btrfs/pg
4. Установить postgres сервер, если не установлен.(Инструкцию можно найти на оф. сайте [3])
1. Создать подраздел btrfs
sudo btrfs subvolume create /mnt/btrfs/pg/$ORIGIN
2. Postgres нужны права на этот каталог
sudo chown postgres:postgres /mnt/btrfs/pg/$ORIGIN
3. Теперь создадим tablespace в этом каталоге. Tablespace может быть назван также как и директория.
psql -c "CREATE TABLESPACE $ORIGIN LOCATION '/mnt/btrfs/pg/$ORIGIN'"
4. Создадим пустую БД в tablespace.
psql -c "CREATE DATABASE $ORIGIN TABLESPACE $ORIGIN;"
pgbench -i -s 10 $ORIGIN
# Будет отображено время затраченное на генерацию
# У pgbench есть и другие параметры, scale только влияет на кол-во записей и
# размер базы. (У меня -s 10 дало базу 92Мб)
1. Создать простой каталог в pg_btrfs для “каркаса” базы $SNAPSHOT. (Пока это будет БД-пустышка, для того чтобы узнать какой OID назначит сервер)
sudo mkdir /mnt/btrfs/pg/$SNAPSHOT
2. Не забудем дать права на этот каталог пользователю postgres.
sudo chown postgres:postgres /mnt/btrfs/pg/$SNAPHOT
3. Создадим в этом каталоге tablespace.
psql -c "CREATE TABLESPACE $SNAPSHOT LOCATION '/mnt/btrfs/pg/$SNAPSHOT'"
4. Создадим пустую БД в этом tablespace.
psql -c "CREATE DATABASE $SNAPSHOT TABLESPACE $SNAPSHOT;"
5. HINT! Теперь нужно запомнить OID, который будет названием каталога внутри созданной структуры директорий после создания БД. Важно учесть, что такой подход позволяет снепшотить только одну базу в tablespace.
/mnt/btrfs/pg/
- $SNAPSHOT/
- PG_11_201809051 # версия postgres (может отличаться)
- 99174299 # - DB OID. Запишем ее в переменную
new_oid=$(sudo ls -1 /mnt/btrfs/pg/$SNAPSHOT/PG_*/ | grep -P [0-9]+)
6. Таким же образом скопируем OID БД $ORIGIN
origin_oid=$(sudo ls -1 /mnt/btrfs/pg/$ORIGIN/PG_*/ | grep -P [0-9]+)
7. Теперь удалим обычный каталог, в котором находится tablespace для снепшота. См. сноску [1].
sudo rm -rf /mnt/btrfs/pg/$SNAPSHOT/
8. И наконец сделаем честный снепшот $ORIGIN через btrfs subvolume
sudo btrfs subvolume snapshot /mnt/btrfs/pg/$ORIGIN/ /mnt/btrfs/pg/$SNAPSHOT
9. В каталоге /mnt/btrfs/pg/$SNAPSHOT будет Copy-on-Write копия $ORIGIN subvolume с OID как в оригинальной БД. Поэтому переименуем ее, чтобы она выглядела для сервера как БД $SNAPSHOT из пункта 4.
cd /mnt/btrfs/pg/$SNAPSHOT/PG_*/
sudo mv $origin_oid $new_oid
cd -
10. Теперь можно подключится к БД $SNAPSHOT и проверить, что там те же данные что и в $ORIGIN.
0. Полезно перед удалением завершить всю активность с базой.
PGQUERY=$(cat<< EOM
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND datname = '$SNAPSHOT';
EOM
)
psql -c "$PGQUERY"
1. Удаляем базу $SNAPSHOT
psql -c "DROP DATABASE IF EXISTS $SNAPSHOT;"
2. Удаляем tablespace $SNAPSHOT
psql -c "DROP TABLESPACE IF EXISTS $SNAPSHOT;
3. Удаляем subvolume btrfs.
btrfs subvolume delete /mnt/btrfs/pg/$SNAPSHOT
1. Повторяем шаги для удаления $SNAPSHOT
2. Повторяем шаги для создания $SNAPSHOT из $ORIGIN
[1] Шаги II.1-6 нужны только для создания OID базы данных в tablespace. Удаление каталога в котором зарегистрирован tablespace не должен сломать postgres(но не думаю, что будет хорошей мыслью делать запросы во время создания снепшота). Мета информация о базах и tablespace-ах продолжает хранится в системной базе postgres, и мы на нее не влияем. Возможно, есть и другой способ создания OID базы данные и его подмена в снепшот $ORIGIN, если вы знаете такой, пожалуйста поделитесь.
P.S. Этот способ очень помог мне на работе, где нужно было каждый день проверять ошибки пользователей в системе на реальных данных, т.е. копии из продакшн. База занимала больше 100Гб, а разворачивание дампа около часа. По старинке, после разворачивания тестовая база захламлялась патчами или миграциями разных разработчиков и данные в ней начинали конфликтовать. Тогда нужно либо иметь запас развернутых копий БД, либо ждать пока удалится и восстановиться новая.
В случае с Btrfs, нужно один раз подождать разворачивание оригинальной базы, а потому за пару секунд создавать снепшоты, и когда необходимо также быстро откатываться к оригинальной базе.
Все эти шаги были вынесены в 3 bash скрипта, которые совпадают с последними тремя разделами, и запускались через jenkins. За год работы проблем на стороне btrfs или postgres замечено не было.
Автор:
r9deyes
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/374661
Ссылки в тексте:
[1] Btrfs: https://btrfs.wiki.kernel.org/index.php/Main_Page
[2] такие инструкции: https://habr.com/ru/post/317660/
[3] на оф. сайте: https://www.postgresql.org/download/
[4] Источник: https://habr.com/ru/post/663878/?utm_source=habrahabr&utm_medium=rss&utm_campaign=663878
Нажмите здесь для печати.