Mysql——3、mysql備份和恢復
一、為什麼要備份?
災難恢復:硬體故障、軟體故障、自然災害、黑客攻擊、誤操作;
測試:
要注意的要點:
可容忍丟失多少資料;
恢復需要在多長時間內完成;
需要恢復哪些資料;
(1)做還原測試,用於測試備份的可用性;
(2)還原演練
二、備份型別
2.1 完全備份,部分備份:
完全備份:整個資料集
部分備份:僅備份其中的一張表或多張表;
2.2 完全備份,增量備份,差異備份
增量備份:僅備份最近一次完全備份或增量備份(如果存在增量)之後變化的資料部分;
差異備份:僅備份最近一次完全備份以來變化的資料;
2.3 熱備份、溫備份和冷備份:
熱備份:線上備份,讀寫操作不受影響;
溫備份:線上備份,讀操作可繼續進行,但寫操作不允許;
冷備份:離線備份,資料庫伺服器離線,備份期間不能為業務提供讀寫服務;
MyISAM: 溫備
InnoDB: 熱備
2.4 物理備份和邏輯備份:
物理備份:直接複製資料檔案進行的備份;
邏輯備份:從資料庫中“匯出”資料另存而進行的備份(與儲存引擎無關);
2.5 規則備份時需要考慮的因素:
持鎖的時長
備份過程時長
備份負載
恢復過程時長
三、備份什麼?
資料、額外的資料(二進位制日誌和InnoDB的事務日誌)、程式碼(儲存過程和儲存函式、觸發器、事件排程器等)、伺服器配置檔案
3.1 設計備份方案:
資料集:完全備份+增量備份;
備份手段:物理備份、邏輯備份;
3.2 備份工具:
(1)mysqldump: 邏輯備份工具,適用於所有儲存引擎,溫備;完全備份,部分備份;對InnoDB儲存引擎支援熱備;
(2)cp, tar等檔案系統工具:物理備份工具,適用於所有儲存引擎;冷備;完全備份,部分備份;
(3)lvm2的快照:幾乎熱備;藉助於檔案系統管理工具實現物理備份;
(4)mysqlhotcopy: 幾乎冷備;僅適用於MyISAM儲存引擎;
3.3 備份工具的選擇:
(1)mysqldump+複製binlog:
mysqldump:完全備份;
複製binlog中指定時間範圍的event:通過備份二進位制日誌實現增量備份;
(2)lvm2快照+binlog:
lvm2快照:使用cp, tar等做物理備份,完全備份;
複製binlog中指定時間範圍的event:增量備份;
(3)xtrabackup:
由Percona提供的支援對InnoDB做熱備(物理備份)的工具,支援完全備份和增量備份
(4)對MyISAM引擎:溫備,只支援完全備份
三、備份工具使用
邏輯備份工具:mysqldump, mydumper, phpMyAdmin
Schema和資料儲存一起、巨大的SQL語句、單個巨大的備份檔案
3.1 mysqldump
客戶端命令,通過mysql協議連線至mysqld;
mysqldump [options] [db_name [tb1_name …]]
命令的語法格式:
mysqldump [OPTIONS] database [tables]:備份單個庫,或庫指定的一個或多個表
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3…]:備份一個或多個庫
mysqldump [OPTIONS] --all-databases [OPTIONS]:備份所有庫
例如: mysqldump -uroot -P13506 -p --databases hellodb > /tmp/hellodb.sql
**3.2 MyISAM:**支援溫備:不能熱備,不能增備;鎖定備份庫,而後啟動備份操作;
鎖定方法:
–lock-all-tables:鎖定所有庫的所有表;
–lock-tables:對於每個單獨的資料庫,在啟動備份之前鎖定其所有表;
對InnoDB表一樣生效,實現溫備;
3.3 InnoDB:支援熱備,增備:
–single-transaction 啟動一個大的單一事務實現備份
-B, --databases db_name1 db_name2 …:備份指定的資料庫
-C, --compress:壓縮傳輸;
其它選項:
-E, --events:備份指定庫的所有事件排程器;
-R, --routines:備份指定庫的儲存過程和儲存函式;
–triggers:備份表相關的觸發器
–master-data[=#]:
1:記錄CHANGE MASTER TO語句;此語句未被註釋;
2:記錄為註釋語句的CHANGE MASTER TO語句;
–flush-logs, -F:鎖定表之後,執行flush logs命令;
注意:二進位制日誌檔案與資料檔案不應該放置於同一磁碟!!!
使用案例:小規模,每週完全備份,每日增量備份
使用一: 用mysqldump實現對指定資料庫的備份;
#!bin/bash
cd /tmp
a=`date +%Y%m%d-%H%M%S`
#備份全部資料庫的資料和結構
mysqldump -u資料使用者名稱 -p資料庫密碼 --all-databases > backup-$a.sql
#備份全部資料庫的結構(加 -d 引數)
#mysqldump -uroot -p123456 -A -d > /data/mydb.sql
#備份全部資料庫的資料(加 -t 引數)
#mysqldump -uroot -p123456 -A -t > /data/mydb.sql
指令碼示例:
1.首先設定各項引數,例如number最多需要備份的數目,備份路徑,使用者名稱,密碼等。
2.執行mysqldump命令儲存備份檔案,並將操作列印至同目錄下的log.txt中標記操作日誌。
3.定義需要刪除的檔案:通過ls命令獲取第九列,即檔名列,再通過head -1實現定義操作時間最晚的那個需要刪除的檔案。
4.定義備份數量:通過ls命令加上wc -l統計以sql結尾的檔案的行數。
5.如果檔案超出限制大小,就刪除最早建立的sql檔案
#!/bin/bash
#儲存備份個數,備份31天資料
number=31
#備份儲存路徑
backup_dir=/root/mysqlbackup
#日期
dd=`date +%Y-%m-%d-%H-%M-%S`
#備份工具
tool=mysqldump
#使用者名稱
username=root
#密碼
password=TankB214
#將要備份的資料庫
database_name=edoctor
#如果資料夾不存在則建立
if [ ! -d $backup_dir ];
then
mkdir -p $backup_dir;
fi
#簡單寫法 mysqldump -u root -p123456 users > /root/mysqlbackup/users-$filename.sql
$tool -u $username -p$password $database_name > $backup_dir/$database_name-$dd.sql
#寫建立備份日誌
echo "create $backup_dir/$database_name-$dd.dupm" >> $backup_dir/log.txt
#找出需要刪除的備份
delfile=`ls -l -crt $backup_dir/*.sql | awk '{print $9 }' | head -1`
#判斷現在的備份數量是否大於$number
count=`ls -l -crt $backup_dir/*.sql | awk '{print $9 }' | wc -l`
if [ $count -gt $number ]
then
#刪除最早生成的備份,只保留number數量的備份
rm $delfile
#寫刪除檔案日誌
echo "delete $delfile" >> $backup_dir/log.txt
fi
定期執行編寫的定時任務指令碼(記得先給shell指令碼執行許可權)
0 2 * * * /root/mysql_backup_script.sh
還原備份檔案(第一種是在MySQL命令列中,第二種是使用SHELL行完成還原):
#1.在系統命令列中,輸入如下實現還原:
mysql -uroot -p123456 < /data/mydb.sql
#2.在登入進入mysql系統中,通過source指令找到對應系統中的檔案進行還原:
mysql> source /data/mydb.sql
使用二:實現利用binary logs完成增量備份;
首先在進行增量備份之前需要檢視一下配置檔案,檢視 log_bin 是否開啟,因為要做增量備份首先要開啟 log_bin 。首先,進入到 myslq 命令列,輸入如下命令:
show variables like '%log_bin%';
如下命令所示,則為未開啟
mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | OFF |
| log_bin_basename | |
| log_bin_index | |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
修改 MySQL 配置項到如下程式碼段:vim /etc/mysql/mysql.conf.d/mysqld.cnf
# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# The MySQL Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#binlog setting,開啟增量備份的關鍵
log-bin=/var/lib/mysql/mysql-bin
server-id=123454
修改之後,重啟 mysql 服務,輸入:
show variables like '%log_bin%';
狀態如下:
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/mysql-bin |
| log_bin_index | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+--------------------------------+
好了,做好了充足的準備,那我們就開始學習增量備份了。
檢視當前使用的 mysql_bin.000*** 日誌檔案,
show master status;
狀態如下:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000015 | 610 | | | |
+------------------+----------+--------------+------------------+-------------------+
當前正在記錄日誌的檔名為 mysql-bin.000015 。
當前資料庫中有如下資料:
mysql> select * from users;
+-------+------+----+
| name | sex | id |
+-------+------+----+
| zone | 0 | 1 |
| zone1 | 1 | 2 |
| zone2 | 0 | 3 |
+-------+------+----+
我們插入一條資料:
insert into `zone`.`users` ( `name`, `sex`, `id`) values ( 'zone3', '0', '4');
檢視效果:
mysql> select * from users;
+-------+------+----+
| name | sex | id |
+-------+------+----+
| zone | 0 | 1 |
| zone1 | 1 | 2 |
| zone2 | 0 | 3 |
| zone3 | 0 | 4 |
+-------+------+----+
我們執行如下命令,使用新的日誌檔案:
mysqladmin -uroot -123456 flush-logs
日誌檔案從 mysql-bin.000015 變為 mysql-bin.000016,而 mysql-bin.000015 則記錄著剛剛 insert 命令的日誌。上句程式碼的效果如下:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000016 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
那麼到現在為止,其實已經完成了增量備份了。
恢復增量備份
那麼現在將剛剛插入的資料刪除,效果如下:
delete from `zone`.`users` where `id`='4'
mysql> select * from users;
+-------+------+----+
| name | sex | id |
+-------+------+----+
| zone | 0 | 1 |
| zone1 | 1 | 2 |
| zone2 | 0 | 3 |
+-------+------+----+
那麼現在就是重點時間了,從 mysql-bin.000015 中恢復資料:
mysqlbinlog /var/lib/mysql/mysql-bin.000015 | mysql -uroot -p123456 zone;
上一句程式碼指定了,需要恢復的 mysql_bin 檔案,指定了使用者名稱:root 、密碼:123456 、資料庫名:zone。效果如下:
mysql> select * from users;
+-------+------+----+
| name | sex | id |
+-------+------+----+
| zone | 0 | 1 |
| zone1 | 1 | 2 |
| zone2 | 0 | 3 |
| zone3 | 0 | 4 |
+-------+------+----+
OK,整一個增量備份的操作流程都在這裡了,那麼我們如何將它寫成指令碼檔案呢,程式碼如下:
#!/bin/bash
#在使用之前,請提前建立以下各個目錄
BakDir=/usr/local/work/backup/daily
#增量備份時複製mysql-bin.00000*的目標目錄,提前手動建立這個目錄
BinDir=/var/lib/mysql
#mysql的資料目錄
LogFile=/usr/local/work/backup/bak.log
BinFile=/var/lib/mysql/mysql-bin.index
#mysql的index檔案路徑,放在資料目錄下的
mysqladmin -uroot -p123456 flush-logs
#這個是用於產生新的mysql-bin.00000*檔案
# wc -l 統計行數
# awk 簡單來說awk就是把檔案逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。
Counter=`wc -l $BinFile |awk '{print $1}'`
NextNum=0
#這個for迴圈用於比對$Counter,$NextNum這兩個值來確定檔案是不是存在或最新的
for file in `cat $BinFile`
do
base=`basename $file`
echo $base
#basename用於擷取mysql-bin.00000*檔名,去掉./mysql-bin.000005前面的./
NextNum=`expr $NextNum + 1`
if [ $NextNum -eq $Counter ]
then
echo $base skip! >> $LogFile
else
dest=$BakDir/$base
if(test -e $dest)
#test -e用於檢測目標檔案是否存在,存在就寫exist!到$LogFile去
then
echo $base exist! >> $LogFile
else
cp $BinDir/$base $BakDir
echo $base copying >> $LogFile
fi
fi
done
echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile
四、物理備份:資料檔案的時間一致性?
基於lvm2快照+cp(tar)的備份
1、請求鎖定所有表:
mysql> FLUSH TABLES WITH READ LOCK;
2、記錄二進位制日誌檔案及事件位置:
mysql> SHOW MASTER STATUS;
mysql -e 'SHOW MASTER STATUS' > /PATH/TO/SOMEFILE
3、建立快照:
lvcreate -L SIZE -s -p r -n NAME /dev/VG_NAME/LV_NAME
如:
lvcreate -L 2G -s -n mydata-snap -p r /dev/myvg/mydata
mke2fs -t ext4 /dev/myvg/mydata-snap
mount /dev/myvg/mydata-snap /data
mkdir -v /data/{mysql,binlogs}
chown -R mysql.mysql /data/*
修改/etc/my.cnf.d/server.conf
的二進位制日誌存放位置:log_bin=/data/binlogs/mysql-bin
啟動資料庫systemctl start mariadb
4、釋放鎖:
mysql> UNLOCK TABLES
5、掛載快照卷,複製資料進行備份;
cp, rsync, tar等命令複製資料;
6、備份完成之後,刪除快照卷;
mysql> SET SESSION sql_log_bin=0;
mysql> SOURCE /path/from/somefile.sql;
mysql> SET SESSION sql_log_bin=1;
mysql> FLUSH TABLES WITH READ LOCK;
mysql> FLUSH LOGS;
7、制定好策略,通過原卷備份二進位制日誌
mysql -e 'SHOW MASTER STATUS';> /root/pos-`date +%F`
五、Xtrabackup(MySQL 資料庫物理熱備的備份工具)
www.percona.com
下載地址:https://www.percona.com/downloads/XtraBackup/LATEST/
innobackupex: 客戶端工具, 以mysql協議連入mysqld,不支援離線備份
完整備份策略:完整備份 + 增量備份 + 二進位制日誌
注意:
1、將資料和二進位制檔案放置於不同的裝置;二進位制日誌也應該週期性地備份;
2、將資料和備份分開存放,建議不在同一裝置、同一主機、同一機房、同一地域;
3、每次災難恢復後都應該立即做一次完全備份;
4、備份後的資料應該週期性地做還原測試;
從備份中恢復應該遵循的步驟:
1、停止MySQL伺服器;
2、記錄伺服器配置和檔案許可權;
3、將備份恢復到MySQL資料目錄;此步驟依賴具體的備份工具;
4、改變配置和檔案許可權;
5、以限制方式啟動MySQL伺服器:比如通過網路訪問;
[mysqld]
skip-networking
socket=/tmp/mysql-recovery.sock
6、載入額外的邏輯備份;而檢查和重放二進位制日誌;
7、檢查已經還原的資料;
8、以完全訪問模式重啟伺服器;
其它的備份工具:
SELECT ... INTO OUTFILE ''
LOAD FILE
mylvmbackup