增量備份的優(yōu)點是沒有重復數據,備份量不大,時間短衫嵌。但缺點也很明顯,需要建立在上次完全備份及完全備份之后所有的增量才能恢復彻秆。
MySQL沒有提供直接的增量備份方法,但是可以通過mysql二進制日志間接實現增量備份结闸。二進制日志對備份的意義如下:
二進制日志保存了所有更新或者可能更新數據的操作
二進制日志在啟動MySQL服務器后開始記錄唇兑,并在文件達到所設大小或者收到flush logs 命令后重新創(chuàng)建新的日志文件
只需定時執(zhí)行flush logs 方法重新創(chuàng)建新的日志,生成二進制文件序列桦锄,并及時把這些文件保存到一個安全的地方扎附,即完成了一個時間段的增量備份。
全量備份
mysqldump --lock-all-tables --flush-logs --master-data=2 -u root -p test > backup_sunday_1_PM.sql
參數 --lock-all-tables
對于InnoDB將替換為 --single-transaction结耀。
該選項在導出數據之前提交一個 BEGIN SQL語句留夜,BEGIN 不會阻塞任何應用程序且能保證導出時數據庫的一致性狀態(tài)。它只適用于事務表图甜,例如 InnoDB 和 BDB碍粥。本選項和 --lock-tables 選項是互斥的,因為 LOCK TABLES 會使任何掛起的事務隱含提交黑毅。要想導出大表的話嚼摩,應結合使用 --quick 選項。
參數 --flush-logs矿瘦,結束當前日志枕面,生成并使用新日志文件
參數 --master-data=2,該選項將會在輸出SQL中記錄下完全備份后新日志文件的名稱缚去,用于日后恢復時參考潮秘,例如輸出的備份SQL文件中含有:CHANGE MASTER TO MASTER_LOG_FILE='MySQL-bin.000002', MASTER_LOG_POS=106;
參數 test,該處的test表示數據庫test易结,如果想要將所有的數據庫備份枕荞,可以換成參數 --all-databases
參數 --databases 指定多個數據庫
參數 --quick或-q柜候,該選項在導出大表時很有用,它強制 MySQLdump 從服務器查詢取得記錄直接輸出而不是取得所有記錄后將它們緩存到內存中买猖。
參數 --ignore-table改橘,忽略某個數據表,如 --ignore-table test.user 忽略數據庫test里的user表
更多mysqldump 參數玉控,請參考網址
全量備份腳本shell
#!/bin/bash
# mysql 數據庫全量備份
# 用戶名飞主、密碼、數據庫名
username="root"
password="tencns152"
dbName="goodthing"
beginTime=`date +"%Y年%m月%d日 %H:%M:%S"`
# 備份目錄
bakDir=/home/mysql/backup
# 日志文件
logFile=/home/mysql/backup/bak.log
# 備份文件
nowDate=`date +%Y%m%d`
dumpFile="${dbName}_${nowDate}.sql"
gzDumpFile="${dbName}_${nowDate}.sql.tgz"
cd $bakDir
# 全量備份(對所有數據庫備份高诺,除了數據庫goodthing里的village表)
/usr/local/mysql/bin/mysqldump -u${username} -p${password} --quick --events --databases ${dbName} --ignore-table=goodthing.village --ignore-table=goodthing.area --flush-logs --delete-master-logs --single-transaction > $dumpFile
# 打包
/bin/tar -zvcf $gzDumpFile $dumpFile
/bin/rm $dumpFile
endTime=`date +"%Y年%m月%d日 %H:%M:%S"`
echo 開始:$beginTime 結束:$endTime $gzDumpFile succ >> $logFile
# 刪除所有增量備份
cd $bakDir/daily
/bin/rm -f *
這里全量備份只備份了一個數據庫碌识,因為如果所有數據庫都備份的話,文件太大了虱而。這里的取舍我也不是很清楚筏餐,畢竟自己還在學習階段,沒有實際的操作經驗牡拇。
增量備份
1. 檢查log_bin是否開啟
進入mysql命令行魁瞪,執(zhí)行 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 |
+---------------------------------+-------+
6 rows in set (0.01 sec)
如上所示,log_bin 未開啟惠呼;如果log_bin開啟导俘,則跳過第2步,直接進入第3步
2. 開啟 log_bin剔蹋,并重啟mysql
編輯 mysql 的配置文件 vim /etc/my.cnf旅薄,在 mysqld 下面添加下面2條配置
[mysqld]
log-bin=/var/lib/mysql/mysql-bin
server_id=152
Tip1: 一定要加 server_id,否則會報錯泣崩。至于server_id的值少梁,隨便設就可以。
Tip2: log_bin 中間可以下劃線_相連矫付,也可以-減號相連凯沪。同理server_id也一樣。
重啟mysql
service mysqld restart
再次在mysql命令行中執(zhí)行 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 |
+---------------------------------+--------------------------------+
6 rows in set (0.01 sec)
3. 備份
進入mysql命令行技即,執(zhí)行 show master status;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 430 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
當前正在記錄日志的文件名是 mysql-bin.000003
比如當前數據庫test的bk_user只有2條記錄
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小紅 | 女 | 21 |
+----+------+------+------+
2 rows in set (0.00 sec)
插入一條新的記錄
mysql> insert into test.bk_user(name, sex, age) values('小強', '男', 24);
Query OK, 1 row affected (0.02 sec)
mysql> select * from test.bk_user;
+----+------+-----+-----+
| id | name | sex | age |
+----+------+-----+-----+
| 1 | 小明 | 男 | 25 |
| 2 | 小紅 | 女 | 21 |
| 5 | 小強 | 男 | 24 |
+----+------+-----+-----+
3 rows in set (0.03 sec)
執(zhí)行命令mysqladmin -uroot -p密碼 flush-logs著洼,生成并使用新的日志文件
再次查看當前使用的日志文件,已經變?yōu)?mysql-bin.000004 了而叼。
mysql-bin.000003 則記錄著剛才執(zhí)行的 insert 語句的日志身笤。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
到這里,其實已經完成了增量備份了葵陵。
恢復增量備份
首先假裝誤刪數據庫記錄
mysql> delete from test.bk_user where id=4;
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小紅 | 女 | 21 |
+----+------+------+------+
2 rows in set (0.00 sec)
從備份的日志文件mysql-bin.000003中恢復數據
[root@centos56 ~]# mysqlbinlog --no-defaults /var/lib/mysql/mysql-bin.000003 | mysql -uroot -p test
Enter password:
ERROR 1032 (HY000) at line 36: Can't find record in 'bk_user'
如果你也遇到這個問題的話液荸,不妨修改 /etc/my.cnf 配置試試。
我在server_id那一行下添加了 slave_skip_errors=1032 脱篙,然后就執(zhí)行成功了娇钱,不再報錯伤柄。
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小紅 | 女 | 21 |
| 5 | 小強 | 男 | 24 |
+----+------+------+------+
3 rows in set (0.00 sec)
增量備份的shell腳本
#!/bin/bash
# 增量備份時復制mysql-bin.00000*的目標目錄,提前手動創(chuàng)建這個目錄
BakDir=/home/mysql/backup/daily
# 日志文件
LogFile=/home/mysql/backup/bak.log
# mysql的數據目錄
BinDir=/var/lib/mysql-bin
# mysql的index文件路徑文搂,放在數據目錄下的
BinFile=/var/lib/mysql-bin/mysql-bin.index
# 這個是用于產生新的mysql-bin.00000*文件
/usr/local/mysql/bin/mysqladmin -uroot -ptencns152 flush-logs
Counter=`wc -l $BinFile | awk '{print $1}'`
NextNum=0
# 這個for循環(huán)用于比對$Counter,$NextNum這兩個值來確定文件是不是存在或最新的
for file in `cat $BinFile`
do
base=`basename $file`
NextNum=`expr $NextNum + 1`
if [ $NextNum -eq $Counter ]
then
echo $base skip! >> $LogFile
else
dest=$BakDir/$base
#test -e用于檢測目標文件是否存在适刀,存在就寫exist!到$LogFile去
if(test -e $dest)
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
定時備份
執(zhí)行命令 crontab -e,添加如下配置
# 每個星期日凌晨3:00執(zhí)行完全備份腳本
0 3 * * 0 /bin/bash -x /root/bash/Mysql-FullyBak.sh >/dev/null 2>&1
# 周一到周六凌晨3:00做增量備份
0 3 * * 1-6 /bin/bash -x /root/bash/Mysql-DailyBak.sh >/dev/null 2>&1
遇到的問題
Can't connect to local MySQL server through socket '/tmp/mysql.sock'
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)'
Check that mysqld is running and that the socket: '/tmp/mysql.sock' exists
去修改mysql的配置文件煤蹭,添加
[mysqladmin]
# 修改為相應的sock
socket=/var/lib/mysql/mysql.sock
執(zhí)行mysqldump時遇到 Unknown table 'column_statistics' in information_schema (1109)
[root@centos56 bash]# /usr/local/mysql/bin/mysqldump -uroot -ptencns152 --quick --events --all-databases --flush-logs --delete-master-logs --single-transaction > /home/mysql/backup/1.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"') FROM information_schema.COLUMN_STATISTICS WHERE SCHEMA_NAME = 'atd' AND TABLE_NAME = 'box_info';': Unknown table 'column_statistics' in information_schema (1109)
如果使用MySQL 8.0+版本提供的命令行工具mysqldump來導出低于8.0版本的MySQL數據庫到SQL文件笔喉,會出現Unknown table 'column_statistics' in information_schema的錯誤,因為早期版本的MySQL數據庫的information_schema數據庫中沒有名為COLUMN_STATISTICS的數據表硝皂。
解決問題的方法是常挚,使用8.0以前版本MySQL附帶的mysqldump工具,最好使用待備份的MySQL服務器版本對應版本號的mysqldump工具稽物,mysqldump可以獨立運行奄毡,并不依賴完整的MySQL安裝包,比如在Windows中贝或,可以直接從MySQL安裝目錄的bin目錄中將mysqldump.exe復制到其他文件夾吼过,甚至從一臺電腦復制到另一臺電腦,然后在CMD窗口中運行咪奖。
當前使用是的MySQL 5.7.22那先。把5.7.20的 MYSQL_HOME/bin/mysqldump 替換掉 5.7.22的,接著就能順利執(zhí)行mysqldump了赡艰,也真是奇了怪了。