作者:Grey
原文地址:
概覽
備份方式 | 說明 | 備注 |
---|---|---|
mysqldump | 默認情況下僅備份:表,視圖和觸發器 | 默認不備份存儲過程和事件,需要加配置參數,如果需要備份存儲過程和事件,需要增加-ER參數,且dump用戶需要增加show events的Global Privilege |
binlog | 有時間期限,可以配置,一般保留5天記錄即可 | |
mysqlpump | 默認備份 表,視圖,存儲過程,存儲函數,觸發器,事件, | MySQL 5.7及以上版本才支持 |
xtrabackup | 需要重啟數據庫,恢復時需要清空數據庫的數據目錄,可以支持增量備份 | 只支持Linux |
基於版本
- MySQL5.7
- Deepin Linux 15.11
- xtrabackup-2.4.18
定時備份腳本(利用MySQL dump)
前置工作
准備一個需要備份的數據庫,假設這個數據庫名稱為cargo,示例腳本如下
CREATE DATABASE IF NOT EXISTS `cargo`;
USE `cargo`;
CREATE TABLE IF NOT EXISTS `b_gen` (
`id` int(11) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `b_gen` (`id`, `name`) VALUES
(1, 'SJA1'),
(2, 'SJA2');
CREATE TABLE IF NOT EXISTS `b_org` (
`id` int(11) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `b_org` (`id`, `name`) VALUES
(1, 'SJA'),
(2, 'ITC');
准備一個用於dump數據庫的用戶,授予以下權限:
-- 創建用戶
create user db_user@'%' identified by 'db_pass';
-- 授權
grant select,show view,lock tables,trigger on cargo.* to db_user@'%' identified by 'db_pass';
flush privileges;
創建存放腳本的目錄
mkdir /data/backup/mysql
腳本目錄結構
- db_bk.sh →主程序
- check_dir.sh→驗證mysql的相關目錄是否存在
- options.conf→全局變量和相關配置
db_bk.sh
#!/bin/bash
DIRNAME=$0
if [ "${DIRNAME:0:1}" = "/" ];then
CURDIR=`dirname $DIRNAME`
else
CURDIR="`pwd`"/"`dirname $DIRNAME`"
fi
echo $CURDIR
# 定義全局變量
. $CURDIR/options.conf
# 檢查相關目錄
. $CURDIR/check_dir.sh
DBname=$1
LogFile=${backup_dir}/db.log
DumpFile=${backup_dir}/DB_${DBname}_$(date +%Y%m%d_%H).sql
NewFile=${backup_dir}/DB_${DBname}_$(date +%Y%m%d_%H).tgz
OldFile=${backup_dir}/DB_${DBname}_$(date +%Y%m%d --date="${expired_days} days ago")*.tgz
[ ! -e "${backup_dir}" ] && mkdir -p ${backup_dir}
DB_tmp=$(${db_install_dir}/bin/mysql -u${dbdumpuser} -p${dbdumppwd} -e "show databases\G" | grep ${DBname})
[ -z "${DB_tmp}" ] && {
echo "[${DBname}] not exist" >>${LogFile}
exit 1
}
if [ -n "$(ls ${OldFile} 2>/dev/null)" ]; then
rm -f ${OldFile}
echo "[${OldFile}] Delete Old File Success" >>${LogFile}
else
echo "[${OldFile}] Delete Old Backup File" >>${LogFile}
fi
if [ -e "${NewFile}" ]; then
echo "[${NewFile}] The Backup File is exists, Can't Backup" >>${LogFile}
else
${db_install_dir}/bin/mysqldump -u${dbdumpuser} -p${dbdumppwd} --databases ${DBname} >${DumpFile}
pushd ${backup_dir} >/dev/null
tar czf ${NewFile} ${DumpFile##*/} >>${LogFile} 2>&1
echo "[${NewFile}] Backup success " >>${LogFile}
rm -f ${DumpFile}
popd >/dev/null
fi
並賦予可執行權限
chmod u+x db_bk.sh
創建備份后的數據庫文件的存放目錄:
mkdir /data/backup/mysql/backup_files
options.conf
# mysql 的安裝路徑,你可以通過以下SQL查看
# select @@basedir as basePath from dual ; show variables like '%basedir%';
mysql_install_dir=/usr/local/mysql
# mysql的數據存儲路徑,你可以通過以下SQL查看
# select @@datadir as dataPath from dual ;show variables Like '%datadir%';
mysql_data_dir=/data/mysql
dbdumpuser=db_user
dbdumppwd=db_pass
# Backup Dest directory, change this if you have someother location
backup_dir=/data/backup/mysql/backup_files
# How many days before the backup directory will be removed
expired_days=5
並賦予可執行權限
chmod u+x options.conf
check_dir.sh
#!/bin/bash
# check MySQL dir
# [ -d "${mysql_install_dir}/support-files" ] && { db_install_dir=${mysql_install_dir}; db_data_dir=${mysql_data_dir}; }
{
db_install_dir=${mysql_install_dir}
db_data_dir=${mysql_data_dir}
}
並賦予可執行權限
chmod u+x check_dir.sh
將這個腳本加到定時任務中:
crontab -e
編輯定時任務文件,增加以下一行,cron表達式意思為:每小時執行一次:
*/60 * * * * /bin/bash /data/backup/mysql/db_bk.sh cargo
定時清理腳本
在/data/backup/mysql/backup_files目錄下創建:deleteLegacy.sh
#!/bin/bash
for file in `find /data/backup/mysql/backup_files/ -type f -name "*"`
do
let expired_time=$[1*24*60*60] #此處定義文件的過期時間1天
let currentDate=`date +%s` #獲取系統時間,所以時間格式為秒
let modifyDate=$(stat -c %Y $file) #獲取文件修改時間
let existTime=$[$currentDate-$modifyDate] #對比時間,算出日志存在時間
if [ $existTime -gt $expired_time ];
then
rm -rf $file #刪除文件
fi
done
並賦予可執行權限
chmod u+x deleteLegacy.sh
加入定時任務
crontab -e
編輯定時任務文件,增加以下一行,cron表達式意思為:每天凌晨1點執行一次:
00 01 * * * /bin/sh /data/backup/mysql/backup_files/deleteLegacy.sh
定時同步腳本
定時同步cargo數據庫到一個新的數據庫(需要提前先建好這個數據庫,假設名字為:cargo_backup)
CREATE DATABASE IF NOT EXISTS `cargo_backup`;
將之前新建的db_user用戶,賦予cargo_backup的所有權限,同時需要設置db_user的Global privileges的SUPER權限(否則導入視圖的時候會有問題
grant all privileges on cargo_backup.* to db_user@'%' identified by 'db_pass';
grant SUPER on *.* to db_user@'%';
flush privileges;
創建同步SQL目錄
mkdir /data/backup/mysql/mysqlsync
腳本參考
mysql_sync.sh
#!/bin/bash
# MySQL數據庫
# 創建一個同步專用用戶(賦予select,show view, trrigger, lock tables權限)
# 對於備份的目標數據庫有所有權限
# 要設置Global privileges的SUPER權限
DB_USER="db_user"
DB_PASS="db_pass"
DB_HOST="localhost"
# 需要備份的數據庫名稱
DB_FROM="cargo"
DB_TO="cargo_backup"
BIN_DIR="/usr/local/mysql/bin"
SYNC_DIR="/data/backup/mysql/mysqlsync"
$BIN_DIR/mysqldump -u$DB_USER -p$DB_PASS -h$DB_HOST $DB_FROM > $SYNC_DIR/sync.sql
$BIN_DIR/mysql -u$DB_USER -p$DB_PASS -h$DB_HOST $DB_TO < $SYNC_DIR/sync.sql
賦予可執行權限
chmod u+x mysql_sync.sh
加入定時任務
crontab -e
編輯定時任務文件,增加以下一行,cron表達式意思為:每天凌晨1點執行一次:
00 01 * * * /bin/bash /data/backup/mysql/backup_files/mysql_sync.sh
采用mysqlpump備份數據庫操作
mysqlpump主要用於備份整個sql執行過程,針對誤操作的情況,我們可以拿mysqlpump中的操作記錄,逐個執行,一直到操作有誤的那個操作停止,這樣就可以撤銷上一次有誤的操作,這種方式的缺點是恢復的時間比較長,優點是可以控制到每一次執行的操作記錄
關於mysqldump和mysqlpump的區別,可以參考MySQL官網對兩個工具的說明:
注:mysqlpump uses MySQL features introduced in MySQL 5.7, and thus assumes use with MySQL 5.7 or higher.
即:MySQL 5.7及以上版本才能使用MySQL pump
ln -s /usr/local/mysql/bin/mysqlpump /usr/bin
grant all privileges on *.* to mysqlpump@'%' identified by 'mysqlpump';
-- grant reload,lock tables,replication client,create tablespace,process,super on *.* to mysqlpump@'%' identified by 'mysqlpump';
FLUSH PRIVILEGES;
備份,假設要備份的數據庫為t,執行
mysqlpump -umysqlpump -pmysqlpump --databases t >t.sql
查看備份后的文件:
t.sql
-- Dump created by MySQL pump utility, version: 5.7.29, Linux (x86_64)
-- Dump start time: Tue Feb 25 19:44:18 2020
-- Server version: 5.7.29
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE;
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET @@SESSION.SQL_LOG_BIN= 0;
SET @OLD_TIME_ZONE=@@TIME_ZONE;
SET TIME_ZONE='+00:00';
SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET NAMES utf8mb4;
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `t` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
CREATE TABLE `t`.`tt` (
`t` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
;
CREATE TABLE `t`.`x` (
`Column 1` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
;
INSERT INTO `t`.`tt` VALUES (2),(2),(2);
SET TIME_ZONE=@OLD_TIME_ZONE;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
SET SQL_MODE=@OLD_SQL_MODE;
-- Dump end time: Tue Feb 25 19:44:18 2020
采用Binlog恢復數據庫
可以查看整個數據庫的操作記錄,對於誤操作的記錄,可以先還原為最近的一次備份,然后將mysqlpump后的sql逐句執行,一直到執行錯誤的那條語句(忽略之)
控制台用root登錄
mysql -uroot -p
show variables like 'binlog_format'
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
binlog的配置在/etc/my.cnf中配置, 若要配置,需要先停數據庫服務
service mysql stop
然后在my.cnf配置這兩個參數
log_bin = mysql-bin
binlog_format = mixed
重啟數據庫
service mysql start
接下來我們模擬幾次操作,我在demo數據庫下建了tsdtas這個表
-- 正常操作
INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1');
INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1');
INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1');
-- 錯誤操作
DELETE FROM `demo`.`tsdtas`;
-- 正常操作
INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1');
INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1');
控制台用root登錄
mysql -uroot -p
執行
flush logs;
在mysql的數據目錄下(一般為:/data/mysql) 找到最新的binlog(格式為:mysql-bin.00000x), 在mysql控制台中
執行:
show binlog events in"mysql-bin.000008";
即可查看所有操作記錄
MySQL [(none)]> show binlog events in"mysql-bin.000008";
+------------------+------+----------------+-----------+-------------+-----------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+------+----------------+-----------+-------------+-----------------------------------------------------------------------+
| mysql-bin.000008 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.29-log, Binlog ver: 4 |
| mysql-bin.000008 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000008 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 219 | Query | 1 | 298 | BEGIN |
| mysql-bin.000008 | 298 | Query | 1 | 429 | use `demo`; INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1') |
| mysql-bin.000008 | 429 | Xid | 1 | 460 | COMMIT /* xid=282 */ |
| mysql-bin.000008 | 460 | Anonymous_Gtid | 1 | 525 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 525 | Query | 1 | 604 | BEGIN |
| mysql-bin.000008 | 604 | Query | 1 | 735 | use `demo`; INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1') |
| mysql-bin.000008 | 735 | Xid | 1 | 766 | COMMIT /* xid=284 */ |
| mysql-bin.000008 | 766 | Anonymous_Gtid | 1 | 831 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 831 | Query | 1 | 910 | BEGIN |
| mysql-bin.000008 | 910 | Query | 1 | 1041 | use `demo`; INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1') |
| mysql-bin.000008 | 1041 | Xid | 1 | 1072 | COMMIT /* xid=286 */ |
| mysql-bin.000008 | 1072 | Anonymous_Gtid | 1 | 1137 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 1137 | Query | 1 | 1216 | BEGIN |
| mysql-bin.000008 | 1216 | Query | 1 | 1317 | use `demo`; DELETE FROM `demo`.`tsdtas` |
| mysql-bin.000008 | 1317 | Xid | 1 | 1348 | COMMIT /* xid=288 */ |
| mysql-bin.000008 | 1348 | Anonymous_Gtid | 1 | 1413 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 1413 | Query | 1 | 1492 | BEGIN |
| mysql-bin.000008 | 1492 | Query | 1 | 1623 | use `demo`; INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1') |
| mysql-bin.000008 | 1623 | Xid | 1 | 1654 | COMMIT /* xid=290 */ |
| mysql-bin.000008 | 1654 | Anonymous_Gtid | 1 | 1719 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 1719 | Query | 1 | 1798 | BEGIN |
| mysql-bin.000008 | 1798 | Query | 1 | 1929 | use `demo`; INSERT INTO `demo`.`tsdtas` (`mm`,`x`) VALUES ('929','1') |
| mysql-bin.000008 | 1929 | Xid | 1 | 1960 | COMMIT /* xid=292 */ |
| mysql-bin.000008 | 1960 | Rotate | 1 | 2007 | mysql-bin.000009;pos=4 |
+------------------+------+----------------+-----------+-------------+-----------------------------------------------------------------------+
在這個操作記錄中,把DELETE語句重新刪掉,其他語句重新執行即可恢復。
采用xtrabackup備份和恢復數據庫
Important: With the introduction of Percona XtraBackup 8.0, Percona XtraBackup 2.4 will continue to support MySQL and Percona Server 5.6 and 5.7 databases. Due to the new MySQL redo log and data dictionary formats the Percona XtraBackup 8.0.x versions will only be compatible with MySQL 8.0.x and the upcoming Percona Server for MySQL 8.0.x
安裝Xtrabackup
tar zxvf percona-xtrabackup-2.4.18-Linux-x86_64.libgcrypt20.tar.gz
cd percona-xtrabackup-2.4.18-Linux-x86_64/bin
cp xtrabackup /usr/bin/xtrabackup
cp innobackupex /usr/bin/innobackupex
創建用戶並授權
# 用戶授權(注:可以限制訪問ip,如本機訪問,可以將%改成localhost)
create user xtrabackup@'%' identified by 'xtrabackup';
grant reload,lock tables,replication client,create tablespace,process,super on *.* to xtrabackup@'%' identified by 'xtrabackup';
# 這里可以指定具體數據庫的增刪改的權限
grant all privileges on *.* to xtrabackup@'%' identified by 'xtrabackup' ;
FLUSH PRIVILEGES;
創建備份目錄
mkdir /data/xtrabackup/
全量備份數據庫
# 查看my.cnf位置:mysql --help | grep 'Default options' -A 1
innobackupex --defaults-file=/etc/my.cnf --user=xtrabackup --password=xtrabackup --socket=/tmp/mysql.sock /data/xtrabackup/
執行完畢后,在/data/xtrabackup下會有一個以時間戳命名的文件夾:類似:2020-02-24_14-42-16
刪除數據庫
# 停止數據庫服務
service mysql stop
# 刪除mysql的data目錄:select @@datadir as dataPath from dual ;
# 假設data目錄為:/data/mysql
cd /data
mv mysql/ mysql_bak/
mkdir mysql
利用 --apply-log來回滾未提交的事務及同步已經提交的事務至數據文件,使數據文件處於一致性狀態。
innobackupex --apply-log /data/xtrabackup/2020-02-24_14-42-16/
恢復
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/xtrabackup/2020-02-24_14-42-16/
配置mysql用戶的數據目錄權限
chmod -R mysql.mysql /data
啟動數據庫
service mysql start
增量備份
我們基於之前的全量備份,做增量備份操作。
首先,模擬增量數據,示例SQL
INSERT INTO `tt` (`t`) VALUES
(5434),
(2),
(3);
innobackupex --defaults-file=/etc/my.cnf --user=xtrabackup --password=xtrabackup --socket=/tmp/mysql.sock --incremental-basedir=/data/xtrabackup/2020-02-24_14-42-16 --incremental /data/xtrabackup/
此時,/data/xtrabackup下會生成一個時間戳文件夾,例如:2020-02-25_14-55-31
這個文件夾是2020-02-24_14-42-16這個備份的增量備份
刪除數據庫
# 停止數據庫服務
service mysql stop
# 刪除mysql的data目錄:select @@datadir as dataPath from dual ;
# 假設data目錄為:/data/mysql
cd /data
mv mysql/ mysql_bak/
mkdir mysql
增量恢復
innobackupex --apply-log --redo-only /data/xtrabackup/2020-02-24_14-42-16
innobackupex --apply-log --redo-only /data/xtrabackup/2020-02-24_14-42-16 --incremental-dir=/data/xtrabackup/2020-02-25_14-55-31
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/xtrabackup/2020-02-24_14-42-16/
配置mysql用戶的數據目錄權限
chown -R mysql.mysql /data
啟動數據庫
service mysql start
使用xtrabackup備份mysql8相關命令
注:來自Percona說法:
Due to changes in MySQL 8.0.20 released by Oracle at the end of April 2020, Percona XtraBackup 8.0, up to version 8.0.11, is not compatible with MySQL version 8.0.20 or higher, or Percona products that are based on it: Percona Server for MySQL and Percona XtraDB Cluster.
簡言之,就是xtrabackup 8 只支持到 MySQL 8.0.20以及以下的版本,對於更高版本,不支持!
mkdir -p /data/backup/mysql/20210520/fulldb
/usr/local/xtrabackup/bin/xtrabackup --defaults-file=/etc/my.cnf --user=young --password=0320 --port=3306 --backup --target-dir=/data/backup/mysql/20210520/fulldb
mkdir -p /data/backup/mysql/20210520/incrdb
/usr/local/xtrabackup/bin/xtrabackup --defaults-file=/etc/my.cnf --user=young --password=0320 --port=3306 --backup --target-dir=/data/backup/mysql/20210520/incrdb --incremental-basedir=/data/backup/mysql/20210520/fulldb
service mysqld stop
mv /data/mysql /data/mysql_bak/
/usr/local/xtrabackup/bin/xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/20210520/fulldb
/usr/local/xtrabackup/bin/xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/20210520/fulldb --incremental-dir=/data/backup/mysql/20210520/incrdb
/usr/local/xtrabackup/bin/xtrabackup --prepare --target-dir=/data/backup/mysql/20210520/fulldb
/usr/local/xtrabackup/bin/xtrabackup -user=young --password=0320 --port=3306 --datadir=/data/mysql --copy-back --target-dir=/data/backup/mysql/20210520/fulldb
chown -R mysql.mysql /data/mysql/
chmod -R 755 /data/mysql/
service mysqld restart