安全的web服務器——使用mysqldump和mysqlbinlog實現MySQL全量與增量備份
1.環境
系統是Deepin15.6,數據庫的版本號是:
Server version: 5.7.18-1 (Debian)
數據庫引擎是:InnoDB。如何查看數據庫版本和數據庫引擎呢?
終端登錄MySQL數據庫命令行的時候,就可以看見數據庫版本。
登錄數據庫後,使用如下命令:
show engines;
它會顯示很多數據庫引擎,其中,顯示YES的指本數據庫支持的引擎,顯示default的是本數據庫默認的引擎。
也可以用如下命令:
show variables like ‘%storage_engine%‘;
來顯示數據庫引擎。
2.全量備份
全量備份很簡單,備份的命令是:
#--databases,指定數據庫 #--flush-logs,產生新的日誌文件,binlog文件,這個在後面的增量備份有講到過 #--delete-master-logs,刪掉原來的日誌文件,binlog文件 #DumpFile是要備份的目標文件 mysqldump -uroot -p123456 --databases wordpressdb --flush-logs --delete-master-logs --single-transaction > $DumpFile恢復的命令是在MySQL命令行中執行的,要先手動創建一個數據庫,然後再use這個數據庫:
mysql> source $DumpFile
3.增量備份
這個操作需要MySQL本身的日誌文件支持,登陸mysql,檢查log-bin是否開啟:
show variables like ‘log_bin‘;
如果如下所示:
mysql> show variables like ‘log_bin‘; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | OFF | +---------------+-------+ 1 row inset (0.00 sec)
顯示OFF的話,那就是沒有開始日誌服務。那麽找到MySQL的配置文件,更改配置,這個地方看了網上的很多教程,但是都沒有用。大概他們講的都是centos上的配置步驟吧,而我用的是基於debian的deepin15.6(Ubuntu應該也是適用的)。配置文件的目錄是
/etc/mysql/mysql.conf.d/mysqld.cnf
在其中加入這麽幾項:
然後,在終端中輸入:sudo service mysql restart 重啟MySQL服務,再登陸上MySQL,執行命令
show variables like ‘log_bin‘;看到如下結果,證明binlog配置成功。
+---------------------------------+--------------------------------+ | Variable_name | Value | +---------------------------------+--------------------------------+ | log_bin | ON | | log_bin_basename | /var/log/mysql/mysql-bin | | log_bin_index | /var/log/mysql/mysql-bin.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+--------------------------------+ 5 rows in set (0.00 sec)
關於binlog日誌的詳細配置用法:
binlog_format 此參數配置binlog的日誌格式,默認為mixed。 max_binlog_size此參數配置binlog的日誌最大值,最大和默認值是1GB。 max_binlog_cache_size此參數表示binlog使用最大內存的數。 binlog-do-db=db_name 此參數表示只記錄指定數據庫的二進制日誌。 binlog-ignore-db=db_name此參數表示不記錄指定的數據庫的二進制日誌。 expire_logs_days 此參數表示binlog日誌保留的時間,默認單位是天。
關於binlog日誌的操作命令:
1.查看所有binlog日誌列表 mysql> show master logs; 2.查看master狀態,即最後(最新)一個binlog日誌的編號名稱,及其最後一個操作事件pos結束點(Position)值,這個文件就是當前MySQL在使用的binlog文件。 mysql> show master status; 3.刷新log日誌,自此刻開始產生一個新編號的binlog日誌文件 mysql> flush logs; 註:每當mysqld服務重啟時,會自動執行此命令,刷新binlog日誌;在mysqldump備份數據時加 -F 選項也會刷新binlog日誌; 4.重置(清空)所有binlog日誌 mysql> reset master;
如果想查看binlog日誌的具體內容,登錄MySQL命令行:
mysql> show binlog events [IN ‘log_name‘] [FROM pos] [LIMIT [offset,] row_count]; 選項解析: IN ‘log_name‘ 指定要查詢的binlog文件名(不指定就是第一個binlog文件) FROM pos 指定從哪個pos起始點開始查起(不指定就是從整個文件首個pos點開始算) LIMIT [offset,] 偏移量(不指定就是0) row_count 查詢總條數(不指定就是所有行)
比如做一下查詢,在mysql-bin.000002文件中查詢pos在219之後的內容:
mysql> show binlog events in ‘mysql-bin.000002‘ from 219; +------------------+-----+------------+-----------+-------------+----------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+------------+-----------+-------------+----------------------------------------+ | mysql-bin.000002 | 219 | Query | 1 | 298 | BEGIN | | mysql-bin.000002 | 298 | Table_map | 1 | 366 | table_id: 241 (wordpressdb.wp_options) | | mysql-bin.000002 | 366 | Write_rows | 1 | 447 | table_id: 241 flags: STMT_END_F | | mysql-bin.000002 | 447 | Xid | 1 | 478 | COMMIT /* xid=53 */ | +------------------+-----+------------+-----------+-------------+----------------------------------------+ 4 rows in set (0.00 sec)
這樣,我們的binlog日誌功能算是做好了。
4.恢復數據實戰
首先,建立一個數據庫,並且插入一些數據:在MySQL程序中輸入以下命令:
mysql> create database AAA; Query OK, 1 row affected (0.00 sec) mysql> use AAA; Database changed mysql> create table BBB(id int); Query OK, 0 rows affected (0.04 sec) mysql> insert into BBB (id) values (1); Query OK, 1 row affected (0.00 sec) mysql> insert into BBB (id) values (2); Query OK, 1 row affected (0.01 sec) mysql> insert into BBB (id) values (3); Query OK, 1 row affected (0.01 sec)
此時,數據庫AAA中的數據庫表BBB中的內容如下所示:
mysql> select * from BBB; +------+ | id | +------+ | 1 | | 2 | | 3 | +------+ 3 rows in set (0.00 sec)
然後,使用MySQL的全量備份,備份整個AAA數據庫:
mysqldump -uroot -p123456 --databases AAA --flush-logs --single-transaction > /home/xu/AAA.sql
然後,我們再對數據庫AAA中的數據庫表BBB做一些操作:
mysql> insert into BBB (id) values (4); Query OK, 1 row affected (0.01 sec) mysql> update BBB set id=5 where id=3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
此時,數據庫AAA中的數據庫表BBB的內容如下所示:
mysql> select * from BBB; +------+ | id | +------+ | 1 | | 2 | | 5 | | 4 | +------+ 4 rows in set (0.00 sec)
接著,不小心刪掉了數據庫AAA:
mysql> drop database AAA; Query OK, 1 row affected (0.03 sec)
此時,迅速的查看當前使用的binlog文件:
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 818 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
這裏,查看這個binlog文件的內容:
mysql> show binlog events in ‘mysql-bin.000003‘; +------------------+-----+----------------+-----------+-------------+-----------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+----------------+-----------+-------------+-----------------------------------------+ | mysql-bin.000003 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.18-1-log, Binlog ver: 4 | | mysql-bin.000003 | 123 | Previous_gtids | 1 | 154 | | | mysql-bin.000003 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘ | | mysql-bin.000003 | 219 | Query | 1 | 290 | BEGIN | | mysql-bin.000003 | 290 | Table_map | 1 | 335 | table_id: 254 (AAA.BBB) | | mysql-bin.000003 | 335 | Write_rows | 1 | 375 | table_id: 254 flags: STMT_END_F | | mysql-bin.000003 | 375 | Xid | 1 | 406 | COMMIT /* xid=1777 */ | | mysql-bin.000003 | 406 | Anonymous_Gtid | 1 | 471 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘ | | mysql-bin.000003 | 471 | Query | 1 | 542 | BEGIN | | mysql-bin.000003 | 542 | Table_map | 1 | 587 | table_id: 254 (AAA.BBB) | | mysql-bin.000003 | 587 | Update_rows | 1 | 633 | table_id: 254 flags: STMT_END_F | | mysql-bin.000003 | 633 | Xid | 1 | 664 | COMMIT /* xid=1778 */ | | mysql-bin.000003 | 664 | Anonymous_Gtid | 1 | 729 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘ | | mysql-bin.000003 | 729 | Query | 1 | 818 | drop database AAA | +------------------+-----+----------------+-----------+-------------+-----------------------------------------+ 14 rows in set (0.00 sec)
從中,我們可以看見,最後一個命令正式刪除數據的操作。
所以,先恢復全量備份的數據庫文件AAA.sql, 在從增量備份文件mysql-bin.000003,恢復文件。因為恢復文件過程中,依然要在binlog中記錄,所以首先要刷新binlog文件:
mysql> flush logs; Query OK, 0 rows affected (0.02 sec) 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-bin.000003中,造成死循環了。並且,在恢復過程中,一定要關閉對數據庫AAA的操作。
首先,手動創建數據庫AAA,然後使用恢復全量文件AAA.sql:
mysql> create database AAA; Query OK, 1 row affected (0.00 sec) mysql> use AAA; Database changed mysql> source /home/xu/AAA.sql Query OK, 0 rows affected (0.00 sec) (…………………………………………………………………………………………) Query OK, 0 rows affected (0.00 sec)
此時,查詢數據庫,有如下結果:
mysql> select * from BBB; +------+ | id | +------+ | 1 | | 2 | | 3 | +------+ 3 rows in set (0.00 sec)
接著,從增量文件mysql-bin.000003中恢復BBB數據庫中的其他數據:
恢復語法格式: # mysqlbinlog mysql-bin.0000xx | mysql -u用戶名 -p密碼 數據庫名 常用選項: --start-position=953 起始pos點 --stop-position=1437 結束pos點 --start-datetime="2013-11-29 13:18:54" 起始時間點 --stop-datetime="2013-11-29 13:21:53" 結束時間點 --database=zyyshop 指定只恢復zyyshop數據庫(一臺主機上往往有多個數據庫,只限本地log日誌) 不常用選項: -u --user=name Connect to the remote server as username.連接到遠程主機的用戶名 -p --password[=name] Password to connect to remote server.連接到遠程主機的密碼 -h --host=name Get the binlog from server.從遠程主機上獲取binlog日誌 --read-from-remote-server Read binary logs from a MySQL server.從某個MySQL服務器上讀取binlog日誌
所以,這裏恢復命令是:
root@DESKTOP-M1SSCB1:/var/log/mysql# mysqlbinlog --stop-position=729 --database=AAA /var/log/mysql/mysql-bin.000003 | mysql -uroot -p123456 -v AAA
註意,在恢復的時候,一定要註意--stop-position這個命令,不然,很可能會使得drop命令還被執行。
再觀察數據庫,可以看到數據庫恢復成功:
mysql> select * from BBB; +------+ | id | +------+ | 1 | | 2 | | 5 | | 4 | +------+ 4 rows in set (0.00 sec)
5.通過腳本實現定時的備份
全量備份的腳本如下:
#!/bin/bash export LANG=en_US.UTF-8 BakDir=/home/xu/mysql/backup LogFile=/home/xu/mysql/backup/bak.log Date=`date +%Y%m%d%H%M%S` Begin=`date +"%Y年%m月%d日 %H:%M:%S"` cd $BakDir DumpFile=$Date.sql GZDumpFile=$Date.sql.tgz #--databases,指定數據庫,所有表格的表結構及其數據 #--flush-logs,產生新的日誌文件,binlog文件,這個在後面的增量備份有講到過 #--delete-master-logs,刪掉原來的日誌文件,binlog文件 #DumpFile是要備份的目標文件 mysqldump -uroot -p123456 --databases wordpressdb --flush-logs --single-transaction > $DumpFile #tar -czvf $GZDumpFile $DumpFile #rm $DumpFile #只保留過去四周的數據庫內容 count=$(ls -l *.sql |wc -l) if [ $count -ge 5 ] then file=$(ls -l *.sql |awk ‘{print $9}‘|awk ‘NR==1‘) rm -f $file fi Last=`date +"%Y年%m月%d日 %H:%M:%S"` echo 開始:$Begin 結束:$Last $GZDumpFile succ >> $LogFile #恢復命令:在MySQL命令行裏面使用source命令 mysql> source /home/xu/mysql/backup/20180804104810.sql
然後,通過crontab來設置定時運行:
vi /etc/crontab #每個星期日淩晨3:00執行完全備份腳本 0 3 * * 0 /......../databak.sh >/dev/null 2>&1
使上述定時任務生效:
crontab /etc/crontab
安全的web服務器——使用mysqldump和mysqlbinlog實現MySQL全量與增量備份