Резервное копирование и восстановление БД
Contents
Резервное копирование и восстановление БД#
Для организации бекапа базы мы рекомендуем локальное снятие дампа. Это происходит быстрее, не грузит сеть. Администратор должен следить за свободным местом на диске, свободного места должно хватать для снятия дампа. Лучше всего для сохранения дампа использовать отдельный том. Это позволяет избежать аварийной остановки постгреса при нехватке места на диске.
Локально снятый дамп архивируется и помещается на внешнее NAS хранилище.
Возможно применение сторонних средств резервного копирования, таких как Кибер Бэкап для PostgreSQL
Снятие дампа#
Снятие дампа выполняется штатной утилитой pg_dump
Для бекапа снимаем только схему public
, ее достаточно для сохранения всех данных системы. Отдельно снимаем структуру всех объектов схемы aud
. Это позволяет при восстановлении не пересоздавать структуры хранения аудита из системы Global.
Если требуется сохранить аудит, то схему aud
рекомендуется снимать отдельно.
Совет
При включенном аудите в системе Global и высокой интенсивности работы схема aud может содержать большие объемы данных (Несколько терабайт). Создание резервной копии схемы aud может занимать продолжительное время.
Обычно все схемы снимаются для переустановки PostgreSQL или обновления версии PostgreSQL, с последующим нагоном полного дампа.
Для снятия дампа используйте формат «Директория». Это позволяет снимать дамп в многопоточном режиме и существенно ускоряет процесс.
Общий пример запуска утилиты снятия дампа
${sDumpUtl} -F d --dbname=postgresql://${sUser}:${sPass}@${sHost}:5432/${sDbName} --jobs=$nColDbJobs --schema=public --blobs --verbose
где
${sDumpUtl} - путь к утилите pg_dump
${sUser} - логин
${sPass} - пароль
${sHost} - хост
${sDbName} - имя бд
$nColDbJobs - количество потоков (выставляется по количеству ядер на сервере postgresql)
Общий пример запуска утилиты для снятия схемы aud
без данных
${sDumpUtl} -F d --dbname=postgresql://${sUser}:${sPass}@${sHost}:5432/${sDbName} --jobs=$nColDbJobs --schema=aud --schema-only --blobs --verbose --file=$sOutputDumpDir
где
${sDumpUtl} - путь к утилите pg_dump
${sUser} - логин
${sPass} - пароль
${sHost} - хост
${sDbName} - имя бд
$nColDbJobs - количество потоков (выставляется по количеству ядер на сервере postgresql)
Совет
Параметр --schema-only
позволяет выгружать только определения объектов (схемы), без данных.
После снятия дампа запаковываем директорию архиватором tar
tar -cvf ${sArchiveDir}/${sTarFileName} $sOutputDumpDir
где
${sArchiveDir} - директория для архива
${sTarFileName} - имя архивного файла
$sOutputDumpDir - директория с дампом
Развертывание дампа#
Внимание
При установке дампа с одного контура на другой, настройки интеграций и шедулера сохраняются, что может привести к проблемам с клонируемым контуром.
Эти настройки нужно обязательно сбрасывать при установке!
Развертывание дампа выполняет штатная утилита pg_restore
Перед развертыванием дампа обязательно удаляем все объекты схемы public
$psqlUtl postgresql://${sUser}:${sPass}@${sHost}:5432/${sDbName} -f $SCRIPTPATH/drop.sql
где
${psqlUtl} - путь к утилите psql
${sUser} - логин
${sPass} - пароль
${sHost} - хост
${sDbName} - имя бд
$SCRIPTPATH - путь до файла drop.sql
файл drop.sql
SET search_path TO public;
--
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT p.oid::regprocedure as sFunctionName
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
inner join pg_roles a on p.proowner =a.oid
WHERE ns.nspname = current_schema
and a.rolname =current_user
and p.probin is null) LOOP
EXECUTE 'DROP FUNCTION IF EXISTS ' || r.sFunctionName || ' CASCADE';
commit;
END LOOP;
END $$;
--
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
commit;
END LOOP;
END $$;
--
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT c.relname
FROM pg_class c
inner join pg_catalog.pg_namespace n on c.relnamespace =n.oid
inner join pg_roles a on c.relowner =a.oid
WHERE (c.relkind = 'S')
and n.nspname =current_schema
and a.rolname =current_user) LOOP
EXECUTE 'drop sequence IF EXISTS ' || quote_ident(r.relname) || ' CASCADE';
commit;
END LOOP;
END $$;
--
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT c.relname
FROM pg_class c
inner join pg_catalog.pg_namespace n on c.relnamespace =n.oid
inner join pg_roles a on c.relowner =a.oid
where c.relkind ='v'
and n.nspname =current_schema
and a.rolname =current_user) LOOP
EXECUTE 'drop view IF EXISTS ' || quote_ident(r.relname) || ' CASCADE';
commit;
END LOOP;
END $$;
--
SELECT lo_unlink(l.oid)
FROM pg_largeobject_metadata l
inner join pg_roles a on l.lomowner =a.oid
WHERE a.rolname =current_user;
Перед развертыванием дампа его нужно распаковать
tar -xvf ${dumpArchiveFile} -C $sTempPath
запустите утилиту развертывания дампа
$sRestoreUtl --dbname=postgresql://${sUser}:${sPass}@${sHost}:5432/${sDbName} -O -x -v --no-tablespaces --jobs=$nColDbJobs $sRealDumpDir
где
$sRestoreUtl - путь к утилите pg_restore
${sUser} - логин
${sPass} - пароль
${sHost} - хост
${sDbName} - имя бд
$nColDbJobs - количество потоков (выставляется по количеству ядер на сервере postgresql)
$sRealDumpDir - путь к каталогу с файлами дампа
Отключение задач в шедуллере#
После поднятия дампа необходимо отключить активные джобы (исключая системные btk), чтобы они не лазили наружу (интеграция например) Скрипт для отключения джоб
update Btk_Job
set benabled = 0
where (ssystemname is null) or (not starts_with(lower(ssystemname), 'btk_'))
JEXL-скрипт для сброса настроек шедулера#
var JObject = function (value) { new ("ru.bitec.app.gtk.lang.json.JObject", value); }
//-----------------------------------------
// Параметры шедулера
var soapHost = "localhost"; // Soap хост
var soapPort = 8080B; // Soap порт (не забудьте 'B' в конце)
var soapReqStr = "/app/sys/soap/sys-service-1.0.0"; // Строка soap запроса
var database = "globalDb"; // База данных
var login = "admin"; // Логин
var pass = "admin"; // Пароль
var publicKey = ""; // Публичный ключ
var isHttpsEnabled = false; // HTTPS включён
//-----------------------------------------
// Скрипт
var idvBtkModule = Btk_SettingApi.getModuleIdByMnemoCode("btk");
var jQuartzProps = null;
if (Btk_SettingApi.isExistsSetting(idvBtkModule, "cQuartzProps")) {
jQuartzProps = JObject(Btk_SettingApi.getSetting(idvBtkModule, "cQuartzProps").asJObject());
} else {
jQuartzProps = JObject({:});
}
jQuartzProps.set("soapHost", soapHost);
jQuartzProps.set("soapPort", soapPort);
jQuartzProps.set("soapReqStr", soapReqStr);
jQuartzProps.set("database", database);
jQuartzProps.set("login", login);
jQuartzProps.set("pass", pass);
jQuartzProps.set("publicKey", publicKey);
jQuartzProps.set("isHttpsEnabled", isHttpsEnabled);
Btk_SettingApi.registerJObject(idvBtkModule, "cQuartzProps", jQuartzProps.underlying(), "");
commit();
JEXL-скрипт для отключения всех интеграций#
// Скрипт отключения всех джобов контуров интеграций
for(row: sql(`
select distinct t.idJob from Rpl_CircuitAgent t
`).asList()) {
var rvCircuitJob = Btk_JobApi.load(row.idjob);
Btk_JobApi.setbEnabled(rvCircuitJob, 0B);
}
commit();
BASH-скрипт выполнения JEXL-кода через API системы#
Bash-скрипт позволяет:
Загружать скрипты из внешних файлов
Авторизоваться в системе
Выполнять код на сервере
Получать результаты выполнения
Скрипт:
#!/bin/bash
# Конфигурация
USERNAME="<username>"
PASSWORD="<password>"
DATABASE="<database>"
URL="<url>"
JEXL_SCRIPT_FILE="<path_to_script>" # Укажите путь к файлу с JEXL-скриптом
# Проверка существования файла со скриптом
if [ ! -f "$JEXL_SCRIPT_FILE" ]; then
echo "Ошибка: файл со скриптом '$JEXL_SCRIPT_FILE' не найден"
exit 1
fi
# Чтение содержимого файла со скриптом
JEXL_SCRIPT=$(<"$JEXL_SCRIPT_FILE")
# Кодирование логина и пароля в base64
BASIC_AUTH=$(echo -n "$USERNAME:$PASSWORD" | base64)
# Формирование тела запроса с помощью jq
JSON_BODY=$(jq -n --arg jexl "$JEXL_SCRIPT" '{jexl: $jexl}')
# Отправка POST-запроса
curl -X POST "$URL/app/sys/rest/ss/pkg/Btk_JexlGatePkg/execute" \
-H "Authorization: Basic $BASIC_AUTH" \
-H "Database: $DATABASE" \
-H "Content-Type: application/json" \
-d "$JSON_BODY"
Требования#
ПО:
curl
7.68+jq
1.6+bash
5.0+
Доступ:
К REST API системы
Чтение файлов скриптов
Конфигурация#
Переменная |
Описание |
Пример значения |
---|---|---|
USERNAME |
Логин администратора |
admin |
PASSWORD |
Пароль |
admin |
DATABASE |
Целевая БД |
globalDb |
URL |
Базовый URL |
|
JEXL_SCRIPT_FILE |
Петь к JEXL скрипту |
/scripts/update_settings.jexl |
Использование#
Исправить переменные в скрипте на свои и запустить его.
bash run_jexl_api.sh
Подставляйте URL со страницы выбора приложений
Например:
На странице выбора приложений такой URL http://globalERP.local/globalDb/?redirect-id=8
, следовательно в переменную подставляем http://globalERP.local/globalDb/