Simple DB backup

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
Строка 298: Строка 298:
вот тока надо знать структуру каждой таблицы, дабы воспользоваться её на этапе 1.
вот тока надо знать структуру каждой таблицы, дабы воспользоваться её на этапе 1.
для этого поможет это скрипт:
для этого поможет это скрипт:
-
 
<source lang="bash">
<source lang="bash">
Строка 310: Строка 309:
done
done
</source>
</source>
 +
 +
Следует с горечью отметить ,что фича "transportable tablespaces" в mysql 5.6 реализована частично и не поддерживает export/import partition-based innodb таблиц. Поэтому таблицы с помесячными логами таким образом восстановить не удасться. Придётся выходить из положения старым способом (http://www.chriscalender.com/?p=28) или использовать percona mysql server или дожидаться выхода oracle community mysql 5.7, в котором эта фича реализована полностью и который получит статус GA уже в этом тысячилетии.

Версия 03:58, 22 мая 2014

Большое спасибо пользователю ok-2004 с форума битела за помощь

UPDATE: Схема проверена и годится для переноса DB на другой сервер.

Используем Percona XtraBackup
Собирать и компилить ничего не надо - качаем binary, просто кидаем содержимое в каталог типа /usr/sbin/ что бы пути не писать.

cat /etc/rc.d/rc.full.backup

#!/bin/bash
 
s_date=`date "+%Y-%m-%d_%H-%M-%S"`
 
s_date_log=$s_date'_log'
 
innobackupex \
--defaults-file=/var/lib/mysql/my.cnf.b \
--no-lock \
--no-timestamp \
--ibbackup=/usr/bin/xtrabackup_55 \
--user=root \
--password=mypassword \
/var/BACKUP/$s_date > /var/BACKUP/$s_date_log 2>&1
 
cp /var/lib/mysql/my.cnf /var/BACKUP/$s_date
tar -cvzf /var/BACKUP/$s_date.tar.gz /var/BACKUP/$s_date >/dev/null 2>&1
rm -rf /var/BACKUP/$s_date

внимание на my.cnf.b - это тот же my.cnf, только пути проставлены полные, типа:
datadir=/var/lib/mysql/db
innodb_data_home_dir = /var/lib/mysql/db
innodb_log_group_home_dir = /var/lib/mysql/log

Перед восстановлением, развернув из архива, бекап надо подготовить:

cat prepare.backup.sh

#!/bin/bash
 
log=$1'_log'
 
innobackupex \
--use-memory=1G \
--defaults-file=/var/lib/mysql/my.cnf.b \
--apply-log \
--ibbackup=xtrabackup_55 \
--user=root \
--password=mypassword \
/var/BACKUP/$1 > /var/BACKUP/$log 2>&1

Само восстановление проводить лучше уже руками:
бездумно не стоит копировать эти строки

#/etc/init.d/mysql stop 
#rm -rf /var/lib/mysql/db 
#mkdir /var/lib/mysql/db
 
#cp -av /var/BACKUP/full/bgbilling /var/lib/mysql/db 
#cp -av /var/BACKUP/full/mysql /var/lib/mysql/db 
#cp -av /var/BACKUP/full/performance_schema /var/lib/mysql/db 
#cp -av /var/BACKUP/full/ibd* /var/lib/mysql/db 
 
#chown -R mysql:mysql /var/lib/mysql/db 
#chown -R mysql:mysql /var/lib/mysql/log 
 
#chmod -R 775 /var/lib/mysql/ 
 
#/etc/init.d/mysql start



P.S.:

Следует отметить, что если ls -al /var/lib/mysql/bgbilling/*.ibd|wc -l будет больше 1024 - процесс бэкапа завершиться с ошибкой. Workaround этого находится в начале следущего "боевого скрипта" который бэкапит базу с числом таких файлов около 1837....:

#!/bin/bash
#/var/bgb/full - временной каталог для бэкапов
#/var/sos/ - подмонтированный через сеть, некий райд-массив...
#боремся с досадным багом перконы
ulimit -n 4096
d=`date +%d%m%g_%M%H`
echo "$d"
if [ -f /var/bgb/stop ]
then
#Предыдущий бэкап сбойнул, уходим отсюда...
echo "STOP FOUND !"
echo "$d stop found !" >> /var/bgb/xtra_log
#Запускаем на компе админа со всего размаху алерт ему в консоль:
export SSH_ASKPASS="/root/p.sh"
export DISPLAY=":0"
#ссашимся на комп админа без пароля но и без предварительного обмена ключами:
##cat p.sh
#!/bin/bash
#echo "МойСамыйСекретныйПарольНаКомпАдмина"
setsid ssh admin@ip.компа.админа "wall \"А у вас очередной бэкап не прошёл... ;) ! \""
exit 1
fi
#############################################################
#Начинаем и навсякий случай сразу напишем завещание
touch /var/bgb/stop
#Расчищаем место :
if [ -d /var/bgb/full ] ; then
rm -rf /var/bgb/full
fi
if [ -f /var/bgb/full_log ] ; then
rm -f /var/bgb/full_log
fi
if [ -f /var/bgb/prep_log ] ; then
rm -f /var/bgb/prep_log
fi
if [ -f /var/bgb/full_ok ] ; then
rm -f /var/bgb/full_ok
fi
if [ -f /var/bgb/prep_ok ] ; then
rm -f /var/bgb/prep_ok
fi
#
echo "FULL BEGIN!"
innobackupex \
--defaults-file=/etc/mysql/my.cnf \
--no-lock \
--no-timestamp \
--ibbackup=/usr/bin/xtrabackup_55 \
--user=root \
--password=xxxxx \
/var/bgb/full > /var/bgb/full_log 2>&1
if [ -z "`tail -1 /var/bgb/full_log | grep 'completed OK!'`" ]
then
#Чота с базой нето... валим отсюда, завещание оставляем 
echo "$d full fail!" >> /var/bgb/xtra_log
echo "FULL FAIL!"
exit 1
else
touch /var/bgb/full_ok
echo "FULL OK!"
fi
##############################################################################
if [ -f /var/bgb/full_ok ] && [ -d /var/bgb/full ]
then
#Вродь бэкап сработал, значит начинаем его приводить в человеческий вид
echo "PREP BEGIN!"
innobackupex \
--use-memory=1G \
--defaults-file=/etc/mysql/my.cnf \
--apply-log \
--ibbackup=xtrabackup_55 \
--user=root \
--password=xxxxx \
/var/bgb/full > /var/bgb/prep_log 2>&1
if [ -z "`tail -1 /var/bgb/prep_log | grep 'completed OK!'`" ]
then
#сбойнуло, валим отсюда, завещание адмниу оставляем...
echo "$d prep fail!" >> /var/bgb/xtra_log
echo "PREP FAIL!"
exit 1
else
touch /var/bgb/prep_ok
echo "PREP OK!"
fi
else
echo "$d full_ok not found!" >> /var/bgb/xtra_log
echo "FULL_OK NOT FOUND!"
exit 1
fi
##################################################################################
if [ -f /var/bgb/prep_ok ] && [ -d /var/bgb/full ]
then
#Бэкап вродь успешен , начинаем копировать на ремотный стораж...
echo "COPY BEGIN!...."
space=`df -h /var/sos|awk '{print $5}'|grep -v Use|cut -d % -f1 -`
case $space in
[1-8]*|9)
echo "/VAR/SOS almost full!"
;;
9[1-9])
echo "/var/sos/ full !" >> /var/bgb/xtra_log
echo "/VAR/SOS/ cleaning...!"
for d_i in `find /var/sos/ -maxdepth 1 -type d \( ! -iname "lost+found" ! -name "*.bak" \) -mtime +30 -print`
do
echo "$d_i" 
read -s -t5 -n1 -r -p "del ? OK ?" key
if [ $? -eq 0 ]; then
    case $key in
        [Yy]* )
rm -rf "$d_i"; 
;;
        * )
echo "$d_i will not deleted"
;;
esac
fi
done
#find /var/sos/ -maxdepth 1 -name "full_*" -type d -mtime +17 -exec rm -rf "{}" \;
;;
esac
rm -f /var/sos/cp_*
if [ -d /var/sos/full ]
then
mv /var/sos/full /var/sos/full_$d
fi
cp -av /var/bgb/full /var/sos > /var/sos/cp_log 2>&1
if [ $? != 0 ]
then
#Чота сегодня не копируется, блин....
echo "$d copy fail!" >> /var/bgb/xtra_log
echo "COPY FAIL!"
exit 1
else
echo "COPY OK!"
#Ну вродь все! Завещание рвём!
rm -f  /var/bgb/stop
fi
else
echo "$d prep_ok not found!" >> /var/bgb/xtra_log
echo "PREP_OK NOT FOUND!"
exit
fi



P.S.2 Вариант и использованием замечательного свойства percona xtrabackup делать "инкрементальные" бэкапы. За день делаются 24 почасовых бэкапа в каталоге "var/bgb/". Отличительным свойством этого скрипта является то, что резервная копия базы почти сразу готова к использованию ( кроме последнего шага, отмеченнного в скрипте с комментариями "!1!" и "!2!".)

#!/bin/bash
#set -x
#бэкапим базу с такими ключами:
ARGS_B="--defaults-file=/etc/mysql/my.cnf --no-lock --no-timestamp --ibbackup=/usr/bin/xtrabackup_55 --user=root --password=xxxxx"
#"препарим" c такими:
ARGS_P="--use-memory=1G --defaults-file=/etc/mysql/my.cnf --apply-log --ibbackup=xtrabackup_55 --user=root --password=xxxxx"
#в файле ордер храним порядковый номер бэкапа в течение дня. (от 0 до 23)
if [ -f /var/bgb/order ]
then
source /var/bgb/order
else
echo "order=0" > /var/bgb/order
order=0
fi
if [[ $order -eq  0 ]]
 then
 # в каталоге inc_0 храним полный бэкап в 0 часов, в каталогах inc_1... inc_23 - почасовые инкрементальные.
  rm -rf /var/bgb/inc_0
  rm -rf /var/bgb/inc_0.bak
  rm -f /var/bgb/*_log
  innobackupex ${ARGS_B}|> /var/bgb/inc_0 > /var/bgb/inc_0_log 2>&1
  # Навсякий случай делаем копию.
  cp -a /var/bgb/inc_0 /var/bgb/inc_0.bak
# "сбэкапили" и тутже частично "препарим" дабы не тратить время когда, настанет час "X"
  innobackupex ${ARGS_P}|>  --redo-only /var/bgb/inc_0 > /var/bgb/prep_0_log 2>&1
  echo "order=1" > /var/bgb/order
 else
order_next=$((order+1))
order_prev=$((order-1))
  rm -rf /var/bgb/inc_${order}|>
  rm -rf /var/bgb/inc_${order}|>.bak
  #бэкапим инкрементально
  innobackupex ${ARGS_B}|> --incremental /var/bgb/inc_${order}|> --incremental-basedir=/var/bgb/inc_${order_prev}|> > /var/bgb/inc_${order}|>_log 2>&1
  cp -a /var/bgb/inc_${order}|> /var/bgb/inc_${order}|>.bak
  case $order in
[1-9]|1[0-9]|2[0-2])
# все промежуточные инкрементальные бэкапы "препарим" частично.
             innobackupex  ${ARGS_P}|>  --redo-only /var/bgb/inc_0  --incremental-dir=/var/bgb/inc_${order}|> > /var/bgb/prep_${order}|>_log 2>&1
             echo "order=$order_next" > /var/bgb/order
        ;;
        23)
# !1! последний дневной бэкап "препарим" полностью.
             innobackupex ${ARGS_P}|> /var/bgb/inc_0 --incremental-dir=/var/bgback/inc_${order}|> > /var/bgb/prep_${order}|>_log 2>&1
# !2! последний "prepare" - полный, чтобы создать логи транзакций iblog*.
             innobackupex ${ARGS_P}|> /var/bgb/inc_0 > /var/bgb/prep_0_${order}|>_log 2>&1
             echo "order=0" > /var/bgb/order
        ;;
   esac
fi

Счастливым обладателям mysql 5.6 ( обладающим свойством transportable tablespaces ) можно изменить строку под комментарием "#!2!..." в виде:

innobackupex ${ARGS_P} --export /var/bgb/exp /var/bgb/inc_0 > /var/bgb/prep_0_${order}_log 2>&1.

В этом случае в каталоге /var/bgb/exp появятся индивидуальные экспортные копии каждой таблицы базы, пригодные для восстановления отдельной таблицы innodb:

0. DROP TABLE crashed_table;
1. CREATE TABLE crashed_table (...) ENGINE=InnoDB;
2. ALTER TABLE crashed_table DISCARD TABLESPACE;
3. cp crashed_table.{ibd,exp,cfg } /var/lib/mysql/bgbilling
4. ALTER TABLE crashed_table IMPORT TABLESPACE;

вот тока надо знать структуру каждой таблицы, дабы воспользоваться её на этапе 1. для этого поможет это скрипт:

#!/bin/bash
mysql -u root -pxxxxx --skip-column-names -e "SELECT table_name FROM information_schema.tables WHERE table_schema = 'bgbilling';" > tables.txt
cat /dev/null > tables_info.txt
for x in `cat tables.txt`
do
echo "=========================" >> tables_info.txt
echo "show create table $x;"|mysql -u root -pxxxxx -N bgbilling >> tables_info.txt
done

Следует с горечью отметить ,что фича "transportable tablespaces" в mysql 5.6 реализована частично и не поддерживает export/import partition-based innodb таблиц. Поэтому таблицы с помесячными логами таким образом восстановить не удасться. Придётся выходить из положения старым способом (http://www.chriscalender.com/?p=28) или использовать percona mysql server или дожидаться выхода oracle community mysql 5.7, в котором эта фича реализована полностью и который получит статус GA уже в этом тысячилетии.

Личные инструменты