null

"Дорогая фея, хочу бэкапы БД MariaDB, да как в Oracle"

Можно сколько угодно спорить о преимуществах/недостатках открытого и проприетарного ПО, но иногда последнее все-таки имеет некоторые преимущества, выражающееся хотя бы в некотором удобстве в работе для администратора.

Задача :

Создание резервных копии "немаленьких" БД с возможностью PITR (Point in Time Recovery) и минимальным влиянием на СУБД. В целом постановка задачи сразу же намекает на использование физических бэкапов с возможностью создания инкрементальных копий.

Как это делается в "кровавом" enterprise-уровня проприетарном решении от Oracle :

При помощи RMAN (Recovery Manager) и простого сценария создаем простую политику инкрементально-обновляемой копии БД (Image Copy) :

RUN {
  RECOVER COPY OF DATABASE WITH TAG 'DB_INC_BACKUP' UNTIL TIME 'SYSDATE - 7';
  BACKUP INCREMENTAL LEVEL 1 FOR RECOVER OF COPY WITH TAG 'DB_INC_BACKUP' DATABASE;
}

Данный сценарий выполнит в первый запуск бэкап уровня 0 (ака Full Backup с возможностью стать "основой" для Incremental), далее будут выполняться инкрементальные бэкап уровня 1 (частота выполнения их уже на совести администратора), восстановление которых ("накат" изменений на бэкап уровня 0) будет выполняться в режиме "плавающего" окна восстановления, равного 7 дням. Таким образом 2.5 строчки кода сценария позволяет нам полностью решить поставленную задачу, бэкап при этом "синтетический" и оптимальный по занимаемому месту для хранения. 

 А теперь посмотрим как реализовать аналогичное, например, для  MariaDB, свободной с оговорками СУБД, которая  часто (и по некоторым возможностям заслуженно) встречается в бизнес-задачах.  

Для поиска аналогичного решения беремся за официальную документацию,  документацию сторонних разработчиков решений enterprise-уровня (например  Percona) на основе свободных версий указанных БД,  обзор поделок на github и тп, но приходим лишь к единственному аналогичному  RMAN  решению - утилите mariabackup (пакет mariadb-backup), "новое" название для продукта xtrabackup. При этом  выясняется , что какой-либо автоматизации для управления резервными копиями здесь нет и весь аналогичный функционал нужно реализовать самостоятельно.

Приведу несколько примеров в виде  функций и  фрагментов  *sh - скрипта, которые можно использовать для написания скрипта реализации РК под свои задачи:

Полный бэкап (первый бэкап, базовый для последующих инкрементальных копий ), в $1 передаем путь "куда положить" полный бэкап: 

bkp_full () {
  /usr/bin/mariabackup --backup --target-dir=$1 --user=$backup_user 
} 

Инкрементальный бэкап на основе указанной предыдущей созданной  копии (полный или инкрементальный бэкап) , в $1 передаем путь "куда положить" инкрементальный бэкап, в $2 - указываем путь до предыдущей созданной копии (полный или инкрементальный бэкап) :

bkp_inc () {
  /usr/bin/mariabackup --backup --target-dir=$1 --incremental-basedir=$2 --user=$backup_user
}

Подготовка полного бэкапа к операции восстановления/наката инкрементальных изменений, по сути это накат  redo логов, которые накопились при выполнении  задачи полного бэкапа (на больших БД это может быть действительно долго), в $1 передаем путь к полному бэкапу :

prep_full () {
  /usr/bin/mariabackup --prepare --target-dir=$1 
}

Подготовка полного бэкапа к операции восстановления/наката инкрементальных изменений, в $1 передаем путь к полному бэкапу, в $2 -  путь к инкрементальному бэкапу

prep_inc () {
  /usr/bin/mariabackup --prepare --target-dir=$1 --incremental-dir=$2
}

Все основные функции готовы, осталось описать процесс, аналогичный указанному выше сценарию Oracle RMAN.

Для простоты изложения приведу основные (упрощенные) этапы выполнения сценария  скрипта и вызовы функций :

rec_win=10080                                            # Окно восстановления в минутах
b_basepath=/db/backup                                    # Базовый путь для хранения бэкапов
full_b_path=$b_basepath/000_fullbackup                   # Полный бэкап
inc_b_path=$b_basepath                                   # Инкрементальные копии

Проверяем не пустая ли директория

dir_empty () {
  /usr/bin/find $1 -empty -type d 
}

Ищем самый "старый" бэкап

oldest_inc_b () {
    declare -a days=($(/usr/bin/ls $inc_b_path))    
        echo ${days[1]}
}

Ищем самый "свежий" бэкап

newest_inc_b () {
    declare -a days=($(/usr/bin/ls $inc_b_path))
        echo ${days[-1]}
}

Делаем первую полную копию, подготавливаем полный бэкап для восстановления

if [[ ! -d "$full_b_path" ]] || [[ "$(dir_empty "$full_b_path")" ]]; then
  /usr/bin/mkdir -p "$full_b_path"
  bkp_full $full_b_path
  prep_full $full_b_path
  exit 0
fi

Определяем самый "свежий" бэкап и путь для "сегодняшней" инкрементальной копии

newest_inc_b_path="$inc_b_path"/"$(newest_inc_b)"
current_inc_b_path="$inc_b_path"/"$(date +%Y%m%d%H%M%S)"

/usr/bin/mkdir -p "$current_inc_b_path"

Создаем инкрементальную копию на основе имеющегося самого "свежего" бэкапа  

if [[ "$current_inc_b_path" != "$newest_inc_b_path"  ]]; then
  bkp_inc "$currest_inc_b_path" "$newest_inc_b_path"
fi

Определяем самый "старый" бэкап и соответствующий ему путь.
Накатываем  самые "старые" копии до выполнения условия - пока есть резервные копии старше даты, заданной в соответствии с параметром окна восстановления, удаляем те копии, которые уже применили при восстановлении.

oldest_inc_b_path="$inc_b_path"/"$(oldest_inc_b)"

if [[ "$oldest_inc_b_path" != "$full_b_path"  ]]; then
  while [ "$(oldest_inc_b)" -lt "$(date --date="$rec_win minute ago" +%Y%m%d%H%M%S)" ]; do
    oldest_inc_b_path="$inc_b_path"/"$(oldest_inc_b)"
    if [[ "$oldest_inc_b_path" != "$full_b_path"  ]]; then
      prep_inc "$full_b_path" "$oldest_inc_b_path" && rm -rf "$oldest_inc_b_path"
    else  
     exit 0      
    fi
  done;
fi  

Таким образом, хоть и гораздо менее комфортно для администатора БД,  достигаем аналогичного решения поставленной задачи, как и с помощью приведенного выше сценария Oracle RMAN.

Коротко о себе:

Работаю в компании TUNE-IT в качестве инженера и преподавателя.

В сферу профессиональных интересов входит все,  что связано с "большими" и не очень серверами и СХД от Sun Microsystems/Oracle и кластерами на их основе, но по долгу службы занимаюсь чаще всего их диагностикой и ремонтом... 

Делюсь опытом и  наработанными навыками в рамках курсов по  соответствующим направлениям.