http://hongge.blog.51cto.com/mysql
MySQL備份通常採起全庫備份加日誌備份的方式,例如天天執行一次全備份,每小時執行一次二進制日誌備份。這樣在MySQL故障後可使用全備份和日誌備份將數據恢復到最後一個二進制日誌備份前的任意位置或時間。sql
一、binlog介紹數據庫
mysql的二進制日誌記錄着該數據庫的全部增刪改的操做日誌(前提是要在本身的服務器上開啓binlog),還包括了這些操做的執行時間。爲了顯示這些二進制內容,咱們可使用mysqlbinlog命令來查看。服務器
Binlog的用途session
1:主從同步app
2:恢復數據庫ide
開啓binary log功能工具
經過編輯my.cnf中的log-bin選項能夠開啓二進制日誌;形式以下:post
log-bin [=DIR/[filename]]學習
其中,DIR參數指定二進制文件的存儲路徑;filename參數指定二級制文件的文件名,其形式爲filename.number,number的形式爲00000一、000002等。每次重啓mysql服務或運行mysql> flush logs;都會生成一個新的二進制日誌文件,這些日誌文件的number會不斷地遞增。除了生成上述的文件外還會生成一個名爲filename.index的文件。這個文件中存儲全部二進制日誌文件的清單又稱爲二進制文件的索引
配置保存之後重啓mysql的服務器,用mysql> show variables like 'log_bin';查看bin-log是否開啓,如圖:
查看產生的binary log 注:查看binlog內容是爲了恢復數據
bin-log由於是二進制文件,不能經過文件內容查看命令直接打開查看,mysql提供兩種方式查看方式,在介紹以前,咱們先對數據庫進行一下增刪改的操做,不然log裏邊數據有點空。
#mysql -uroot -p -e "reset master"
#mysql -uroot -p -e "create database test"
#mysql -uroot -p -e "use test;create table tb1(id int primary key auto_increment,name varchar(20))"
#mysql -uroot -p -e "insert into test.tb1(name) values('lisi')"
#mysql -uroot -p -e "insert into test.tb1(name) values('zhangsan')"
從新開始一個新的日誌文件
#mysql -uroot -p -e "flush logs"
#mysql -uroot -p -e "delete from test.tb1 where id=2"
#mysql -uroot -p -e "insert into test.tb1(name) values('tom')"
# mysql -uroot -p -e "select * from test.tb1"
Enter password:
+----+------+
| id | name |
+----+------+
| 1 | lisi |
| 3 | tom |
+----+------+
查看MySQL Server上的二進制日誌
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 1087 |
| mysql-bin.000002 | 673 |
+------------------+-----------+
查看二進制日誌信息的命令:
語法格式:SHOW BINLOG EVENTS [IN
'log_name'] [FROM pos] [LIMIT [offset,] row_count]
查看二進制日誌中的事件
mysql> show binlog events;
默認顯示可找到的第一個二進制日誌文件中的事件,包含了日誌文件名、事件的開始位置、事件類型、結束位置、信息等內容
+------------------+------+----------------+-----------+-------------+----------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+------+----------------+-----------+-------------+----------------------------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.13-log, Binlog ver: 4 | //此事件爲格式描述事件
| mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000001 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 219 | Query | 1 | 313 | create database test | //爲查詢事件
| mysql-bin.000001 | 313 | Anonymous_Gtid | 1 | 378 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 378 | Query | 1 | 520 | use `test`; create table tb1(id int primary key auto_increment,name varchar(20)) |
| mysql-bin.000001 | 520 | Anonymous_Gtid | 1 | 585 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 585 | Query | 1 | 653 | BEGIN | //爲查詢事件,事務開始
| mysql-bin.000001 | 653 | Table_map | 1 | 702 | table_id: 110 (test.tb1) | //爲表映射事件
| mysql-bin.000001 | 702 | Write_rows | 1 | 747 | table_id: 110 flags: STMT_END_F | //爲咱們執行的insert事件
| mysql-bin.000001 | 747 | Xid | 1 | 778 | COMMIT /* xid=2052 */ | //Xid時間是自動提交事務的動做
| mysql-bin.000001 | 778 | Anonymous_Gtid | 1 | 843 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 843 | Query | 1 | 911 | BEGIN |
| mysql-bin.000001 | 911 | Table_map | 1 | 960 | table_id: 110 (test.tb1) |
| mysql-bin.000001 | 960 | Write_rows | 1 | 1009 | table_id: 110 flags: STMT_END_F |
| mysql-bin.000001 | 1009 | Xid | 1 | 1040 | COMMIT /* xid=2055 */ |
| mysql-bin.000001 | 1040 | Rotate | 1 | 1087 | mysql-bin.000002;pos=4 | //爲日誌輪換事件,是咱們執行flush logs開啓新日誌文件引發的。
查看指定的二進制日誌中的事件
mysql> show binlog events in 'mysql-bin.000002';
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000002 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.13-log, Binlog ver: 4 |
| mysql-bin.000002 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000002 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 219 | Query | 1 | 287 | BEGIN |
| mysql-bin.000002 | 287 | Table_map | 1 | 336 | table_id: 110 (test.tb1) |
| mysql-bin.000002 | 336 | Delete_rows | 1 | 385 | table_id: 110 flags: STMT_END_F |
| mysql-bin.000002 | 385 | Xid | 1 | 416 | COMMIT /* xid=2068 */ |
| mysql-bin.000002 | 416 | Anonymous_Gtid | 1 | 481 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 481 | Query | 1 | 549 | BEGIN |
| mysql-bin.000002 | 549 | Table_map | 1 | 598 | table_id: 110 (test.tb1) |
| mysql-bin.000002 | 598 | Write_rows | 1 | 642 | table_id: 110 flags: STMT_END_F |
| mysql-bin.000002 | 642 | Xid | 1 | 673 | COMMIT /* xid=2071 */ |
該命令還包含其餘選項以便靈活查看
mysql> show binlog events in 'mysql-bin.000002' from 219 limit 1,3;
+------------------+-----+-------------+-----------+-------------+---------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+-------------+-----------+-------------+---------------------------------+
| mysql-bin.000002 | 287 | Table_map | 1 | 336 | table_id: 110 (test.tb1) |
| mysql-bin.000002 | 336 | Delete_rows | 1 | 385 | table_id: 110 flags: STMT_END_F |
| mysql-bin.000002 | 385 | Xid | 1 | 416 | COMMIT /* xid=2068 */ |
SHOW BINARY LOGS 等價於 SHOW MASTER LOGS
PURGE BINARY LOGS用於刪除二進制日誌,如:
PURGE BINARY LOGS TO 'mysql-bin.00010'; //把這個文件以前的其餘文件都刪除掉
PURGE BINARY LOGS BEFORE '2016-08-28 22:46:26';//把指定時間以前的二進制文件刪除了
RESET MASTER 與 RESET SLAVE
前者清空index文件中列出的全部二進制日誌,重置index文件爲空,並建立一個新的二進制日誌文件,通常用於MASTER首次啓動時。後者使SLAVE忘記其在MASTER二進制日誌文件中的複製位置,它會刪除master.info、relay-log.info 和全部中繼日誌文件並開始一個新的中繼日誌文件,以便於開始一個乾淨的複製。在使用RESET SLAVE前需先關閉 SLAVE複製線程。
上述方式能夠查看到服務器上存在的二進制日誌文件及文件中的事件,可是想查看到文件中具體的內容並應於恢復場景還得藉助mysqlbinlog這個工具。
語法格式: mysqlbinlog [options] log_file ...
輸出內容會因日誌文件的格式以及mysqlbinlog工具使用的選項不一樣而略不一樣。
mysqlbinlog的可用選項可參考man手冊。
二進制日誌文件的格式包含行模式、語句模式和混合模式(也即有服務器決定在什麼狀況下記錄什麼類型的日誌),基於語句的日誌中事件信息包含執行的語句等,基於行的日誌中事件信息包含的是行的變化信息等。混合模式的日誌中兩種類型的事件信息都會記錄。
爲了便於查看記錄了行變化信息的事件在當時具體執行了什麼樣的SQL語句可使用mysqlbinlog工具的-v(--verbose)選項,該選項會將行事件重構成被註釋掉的僞SQL語句,若是想看到更詳細的信息能夠將該選項給兩次如-vv,這樣能夠包含一些數據類型和元信息的註釋內容,如
先切換到binlog所在的目錄下
#mysqlbinlog mysql-bin.000001
#mysqlbinlog -v mysql-bin.000001
#mysqlbinlog -vv mysql-bin.000001
另外mysqlbinlog和能夠經過--read-from-remote-server選項從遠程服務器讀取二進制日誌文件,這時須要一些而外的鏈接參數,如-h,-P,-p,-u等,這些參數僅在指定了--read-from-remote-server後有效。
不管是本地二進制日誌文件仍是遠程服務器上的二進制日誌文件,不管是行模式、語句模式仍是混合模式的二進制日誌文件,被mysqlbinlog工具解析後均可直接應用與MySQL Server進行基於時間點、位置或數據庫的恢復。
下面咱們就來演示如何使用binlog恢復以前刪除數據(id=2那條記錄)
注意:在實際生產環境中,若是遇到須要恢復數據庫的狀況,不要讓用戶能訪問到數據庫,以免新的數據插入進來,以及在主從的環境下,關閉主從。
查看binlog文件,從中找出delete from test.tb1 where id=2
# cd /usr/local/mysql/data/
# mysqlbinlog -v mysql-bin.000002
顯示結果
# at 219
#160913 20:59:51 server id 1 end_log_pos 287 CRC32 0x1a97741b Query thread_id=42 exec_time=0 error_code=0
SET TIMESTAMP=1473771591/*!*/;
SET @@session.pseudo_thread_id=42/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 287
#160913 20:59:51 server id 1 end_log_pos 336 CRC32 0x930ab248 Table_map: `test`.`tb1` mapped to number 125
# at 336
#160910 23:17:43 server id 1 end_log_pos 385 CRC32 0xdede3eb7 Delete_rows: table id 110 flags: STMT_END_F
BINLOG '
FyTUVxMBAAAAMQAAAFABAAAAAG4AAAAAAAEABHRlc3QAA3RiMQACAw8CPAAC2t7UdQ==
FyTUVyABAAAAMQAAAIEBAAAAAG4AAAAAAAEAAgAC//wCAAAACHpoYW5nc2Futz7e3g==
'/*!*/;
### DELETE FROM `test`.`tb1`
### WHERE
### @1=2
### @2='zhangsan'
# at 385
#160910 23:17:43 server id 1 end_log_pos 416 CRC32 0x7881c9da Xid = 2068
COMMIT/*!*/;
從中能夠看出delete事件發生position是287,事件結束position是416
恢復流程:直接用bin-log日誌將數據庫恢復到刪除位置287前,而後跳過故障點,再進行恢復下面全部的操做,命令以下
因爲以前沒有作過全庫備份,因此要使用全部binlog日誌恢復,因此生產環境中須要很長時間恢復,導出相關binlog文件
#mysqlbinlog /usr/local/mysql/data/mysql-bin.000001 > /opt/mysql-bin.000001.sql
#mysqlbinlog --stop-position=287 /usr/local/mysql/data/mysql-bin.000002 > /opt/287.sql
#mysqlbinlog --start-position=416 /usr/local/mysql/data/mysql-bin.000002 > /opt/416.sql
刪除test數據庫
mysql>drop database test;
利用binlog恢復數據
#mysql -uroot -p123456< /opt/mysql-bin.000001.sql
#mysql -uroot -p123456< /opt/287.sql
#mysql -uroot -p123456< /opt/416.sql
恢復完成後,咱們檢查下表的數據是否完整
mysql> select * from test.tb1;
+----+----------+
| id | name |
+----+----------+
| 1 | lisi |
| 2 | zhangsan |
| 3 | tom |
+----+----------+
Ok完整的都恢復過來了
mysqlbinlog 選項示例
常見的選項有如下幾個:
--start-datetime
從二進制日誌中讀取指定時間戳或者本地計算機時間以後的日誌事件。
--stop-datetime
從二進制日誌中讀取指定時間戳或者本地計算機時間以前的日誌事件。
--start-position
從二進制日誌中讀取指定position 事件位置做爲開始。
--stop-position
從二進制日誌中讀取指定position 事件位置做爲事件截至。
二、mysqldump介紹
mysqldump是mysql用於備份和數據轉移的一個工具。它主要產生一系列的SQL語句,能夠封裝到文件,該文件包含有全部重建你的數據庫所須要的 SQL命令如CREATE DATABASE,CREATE TABLE,INSERT等等。能夠用來實現輕量級的快速遷移或恢復數據庫。
mysqldump 是將數據表導成 SQL 腳本文件,在不一樣的 MySQL 版本之間升級時相對比較合適,這也是最經常使用的備份方法。
mysqldump通常在數據量很小的時候(幾個G)能夠用於備份。當數據量比較大的狀況下,就不建議用mysqldump工具進行備份了。
數據庫的導出
導出對象說明:
mysqldump能夠針對單個表、多個表、單個數據庫、多個數據庫、全部數據庫進行導出的操做
# mysqldump [options] db_name [tbl_name ...] //導出指定數據庫或單個表
# mysqldump [options] --databases db_name ... //導出多個數據庫
#mysqldump [options] --all-databases //導出全部
導出數據庫test
# mysqldump -uroot -p --flush-logs test > /opt/test.sql //--flush-logs這個選項就會完整備份的時候從新開啓一個新binlog
數據庫的導入
# mysql -uroot -p test < /opt/test.sql
在前面咱們介紹了mysql的binlog和mysqldump工具,下面咱們來學習如何實現mysqldump全庫備份+binlog的數據恢復
環境準備與備份還原:
檢查開啓binlog
先建立一些原始數據
mysql> reset master;
mysql> create database test_db;
mysql> use test_db;
mysql> create table tb1(id int primary key auto_increment,name varchar(20));
mysql> insert into tb1(name) values('tom1');
mysql> insert into tb1(name) values('tom2');
mysql> commit;
mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
+----+------+
方案:mysqldump全庫備份+binlog還原
一、mysqldump備份方案:
每週一凌晨1點全庫備份
二、備份步驟
(1) 建立備份目錄
# mkdir /opt/mysqlbackup
# mkdir /opt/mysqlbackup/daily
(2)全庫備份
這裏咱們模擬週一的完整備份數據庫任務
#mysqldump -uroot -p --flush-logs test_db > /opt/mysqlbackup/test_db_2016_09_12.sql
[root@localhost data]# ls -l /opt/mysqlbackup/
-rw-r--r--. 1 root root 1871 Sep 13 21:06 test_db_2016_09_12.sql
備份mysqldump全庫備份以前的binlog日誌文(注:生產環境中可能不僅一個binlog文件)
# cp /usr/local/mysql/data/mysql-bin.000001 /opt/mysqlbackup/daily/
# mysql -uroot -p -e "purge binary logs to 'mysql-bin.000002'"
模擬下操做失誤,將數據修改錯誤了。
mysql> use test_db;
mysql> delete from tb1 where id=1;
mysql> commit;
mysql> insert into tb1(name) values('tom3');
mysql> commit;
備份自mysqldump以後的binlog日誌文件
cp /usr/local/mysql/data/mysql-bin.000002 /opt/mysqlbackup/daily/
上面的模擬的誤操做是刪除了id=1的記錄
(3)如今咱們使用mysqldump的全庫備份和binlog來恢復數據。
使用mysqldump的備份進行全庫恢復
# mysql -uroot -p test_db < /opt/mysqlbackup/test_db_2016_09_12.sql
查詢一下數據
[root@localhost ~]# mysql -uroot -p -e "select * from test_db.tb1"
Enter password:
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
+----+------+
從顯示結果能夠看到使用mysqldump備份將數據還原到了備份時的狀態,剛纔刪除的數據(id=2)恢復回來了,但備份後產生的數據卻丟失了因此還得利用binlog進一步不原
由於刪除是在全庫備份後發生的,而mysqldump全庫備份時使用--flush-logs選項,因此只須要分析全庫備份後的binlog即mysql-bin.000002。
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000002 | 1853 |
+------------------+-----------+
查看mysql-bin.000002中的事件,能夠看到有刪除事件
mysql> show binlog events in 'mysql-bin.000002';
| mysql-bin.000002 | 219 | Query | 1 | 294 | BEGIN |
| mysql-bin.000002 | 294 | Table_map | 1 | 346 | table_id: 118 (test_db.tb1) |
| mysql-bin.000002 | 346 | Delete_rows | 1 | 391 | table_id: 118 flags: STMT_END_F |
| mysql-bin.000002 | 391 | Xid | 1 | 422 | COMMIT /* xid=2739 */
使用mysqlbinlog 命令能夠查看備份的binlog文件的詳細事件。
恢復流程:咱們直接用bin-log日誌將數據庫恢復到刪除位置前,而後跳過故障點,再進行恢復刪除後的全部操做。
# mysqlbinlog -v /opt/mysqlbackup/daily/mysql-bin.000002
咱們先用mysqlbinlog命令找到delete那條語句的位置
# at 219
#160911 17:19:55 server id 1 end_log_pos 294 CRC32 0x84590493 Query thread_id=66 exec_time=0 error_code=0
SET TIMESTAMP=1473585595/*!*/;
SET @@session.pseudo_thread_id=66/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 294
#160911 17:19:55 server id 1 end_log_pos 346 CRC32 0x5cdccf9e Table_map: `test_db`.`tb1` mapped to number 118
# at 346
#160911 17:19:55 server id 1 end_log_pos 391 CRC32 0x320c4935 Delete_rows: table id 118 flags: STMT_END_F
BINLOG '
uyHVVxMBAAAANAAAAFoBAAAAAHYAAAAAAAEAB3Rlc3RfZGIAA3RiMQACAw8CPAACns/cXA==
uyHVVyABAAAALQAAAIcBAAAAAHYAAAAAAAEAAgAC//wBAAAABHRvbTE1SQwy
'/*!*/;
### DELETE FROM `test_db`.`tb1`
### WHERE
### @1=1
### @2='tom1'
# at 391
#160911 17:19:55 server id 1 end_log_pos 422 CRC32 0x5e4a6699 Xid = 2739
COMMIT/*!*/;
經過mysqlbinlog命令所顯示的結果能夠看到誤操做delete的開始postion爲219,結束position是422。
從二進制日誌中讀取指定position=219事件位置做爲截至,即把數據恢復到delete刪除前
# mysqlbinlog --stop-position=219 /opt/mysqlbackup/daily/mysql-bin.000002 | mysql -u root -p
從二進制日誌中讀取指定position=422事件位置做爲開始,即跳過刪除事件,恢復刪除事件以後對數據的正常操做
#mysqlbinlog --start-position=422 /opt/mysqlbackup/daily/mysql-bin.000002 | mysql -u root -p
查看恢復結果:
# mysql -uroot -p -e "select * from test_db.tb1"
Enter password:
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
| 3 | tom3 |
+----+------+
從上面顯示能夠看出數據恢復到正常狀態