數據備份 恢復
NSD DBA1 DAY06
1 數據備份與恢復
1.1 問題
本案例要求熟悉MySQL的備份與恢復,完成以下任務操作:
- 邏輯備份工具 mysqldump
- 使用mysql 恢復數據庫
1.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:使用mysqldump進行邏輯備份
1)備份MySQL服務器上的所有庫
將所有的庫備份為mysql-all.sql文件:
- [[email protected] ~]# mysqldump -u root -p --all-databases > /root/alldb.sql
- Enter password: //驗證口令
- [[email protected] mysql]# file /root/alldb.sql //確認備份文件類型
- /root/alldb.sql: UTF-8 Unicode English text, with very long lines
查看備份文件alldb.sql的部分內容:
- [[email protected] ~]# grep -vE ‘^/|^-|^$‘ /root/alldb.sql | head -15
- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `home` /*!40100 DEFAULT CHARACTER SET latin1 */;
- USE `home`;
- DROP TABLE IF EXISTS `biao01`;
- CREATE TABLE `biao01` (
- `id` int(2) NOT NULL,
- `name` varchar(8) DEFAULT NULL
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
- LOCK TABLES `biao01` WRITE;
- UNLOCK TABLES;
- DROP TABLE IF EXISTS `biao02`;
- CREATE TABLE `biao02` (
- `id` int(4) NOT NULL,
- `name` varchar(8) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
- .. ..
註意:若數據庫都使用MyISAM存儲引擎,可以采用冷備份的方式,直接復制對應的數據庫目錄即可;恢復時重新復制回來就行。
2)只備份指定的某一個庫
將userdb庫備份為userdb.sql文件:
- [[email protected] ~]# mysqldump -u root -p userdb > userdb.sql
- Enter password: //驗證口令
查看備份文件userdb.sql的部分內容:
- [[email protected] ~]# grep -vE ‘^/|^-|^$‘ /root/userdb.sql
- DROP TABLE IF EXISTS `stu_info`;
- CREATE TABLE `stu_info` (
- `name` varchar(12) NOT NULL,
- `gender` enum(‘boy‘,‘girl‘) DEFAULT ‘boy‘,
- `age` int(3) NOT NULL
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
- LOCK TABLES `stu_info` WRITE;
- .. ..
3)同時備份指定的多個庫
同時備份mysql、userdb庫,保存為mysql+userdb.sql文件:
- [[email protected] ~]# mysqldump -u root -p -B mysql userdb > mysql+test+userdb.sql
- Enter password: //驗證口令
查看備份文件userdb.sql的部分內容:
- [[email protected] ~]# grep ‘^CREATE DATA‘ /root/mysql+userdb.sql
- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysql` /*!40100 DEFAULT CHARACTER SET latin1 */;
- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `userdb` /*!40100 DEFAULT CHARACTER SET latin1 */;
步驟二:使用mysql命令從備份中恢復數據庫、表
以恢復userdb庫為例,可參考下列操作。通常不建議直接覆蓋舊庫,而是采用建立新庫並導入邏輯備份的方式執行恢復,待新庫正常後即可廢棄或刪除舊庫。
1)創建名為userdb2的新庫
- mysql> CREATE DATABASE userdb2;
- Query OK, 1 row affected (0.00 sec)
2)導入備份文件,在新庫中重建表及數據
- [[email protected] ~]# mysql -u root -p userdb2 < /root/userdb.sql
- Enter password: //驗證口令
3)確認新庫正常,啟用新庫
- mysql> USE userdb2; //切換到新庫
- Reading table information for completion of table and column names
- You can turn off this feature to get a quicker startup with -A
- Database changed
- mysql> SELECT sn,username,uid,gid,homedir //查詢數據,確認可用
- -> FROM userlist LIMIT 10;
- +----+----------+-----+-----+-----------------+
- | sn | username | uid | gid | homedir |
- +----+----------+-----+-----+-----------------+
- | 1 | root | 0 | 0 | /root |
- | 2 | bin | 1 | 1 | /bin |
- | 3 | daemon | 2 | 2 | /sbin |
- | 4 | adm | 3 | 4 | /var/adm |
- | 5 | lp | 4 | 7 | /var/spool/lpd |
- | 6 | sync | 5 | 0 | /sbin |
- | 7 | shutdown | 6 | 0 | /sbin |
- | 8 | halt | 7 | 0 | /sbin |
- | 9 | mail | 8 | 12 | /var/spool/mail |
- | 10 | operator | 11 | 0 | /root |
- +----+----------+-----+-----+-----------------+
- 10 rows in set (0.00 sec)
4)廢棄或刪除舊庫
- mysql> DROP DATABASE userdb;
- Query OK, 2 rows affected (0.09 sec)
2 使用binlog日誌
2.1 問題
利用binlog恢復庫表,要求如下:
- 啟用binlog日誌
- 創建db1庫tb1表,插入3條記錄
- 刪除tb1表中剛插入的3條記錄
- 使用mysqlbinlog恢復刪除的3條記錄
2.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:啟用binlog日誌
1)調整/etc/my.cnf配置,並重啟服務
- [[email protected] ~]# vim /etc/my.cnf
- [mysqld]
- .. ..
- log-bin-index=mysql-bin //啟用二進制日誌,並指定前綴
- server_id=1
- binlog_format=STATEMENT
- //在Mysql5.7中,binlog日誌格式默認為ROW,但它不記錄sql語句上下文相關信息。需要將binlog日誌格式修改為STATEMENT
- .. ..
- [[email protected] ~]# systemctl restart mysqld.service
2)確認binlog日誌文件
新啟用binlog後,每次啟動MySQl服務都會新生成一份日誌文件:
- [[email protected] ~]# ls /var/lib/mysql/mysql-bin.*
- /var/lib/mysql/mysql-bin.000001 /var/lib/mysql/mysql-bin.index
其中mysql-bin.index文件記錄了當前保持的二進制文件列表:
- [[email protected] ~]# cat /var/lib/mysql/mysql-bin.index
- ./mysql-bin.000001
重啟MySQL服務程序,或者執行SQL操作“FLUSH LOGS;”,會生成一份新的日誌:
- [[email protected] ~]# ls /var/lib/mysql/mysql-bin.*
- /var/lib/mysql/mysql-bin.000001 /var/lib/mysql/mysql-bin.index
- /var/lib/mysql/mysql-bin.000002
- [[email protected] ~]# cat /var/lib/mysql/mysql-bin.index
- ./mysql-bin.000001
- ./mysql-bin.000002
步驟二:利用binlog日誌重做數據庫操作
1)執行數據庫表添加操作
創建db1·庫tb1表,表結構自定義:
- mysql> CREATE DATABASE db1;
- Query OK, 1 row affected (0.05 sec)
- mysql> USE db1;
- Database changed
- mysql> CREATE TABLE tb1(
- -> id int(4) NOT NULL,name varchar(24)
- -> );
- Query OK, 0 rows affected (0.28 sec)
插入3條表記錄:
- mysql> INSERT INTO tb1 VALUES
- -> (1,‘Jack‘),
- -> (2,‘Kenthy‘),
- -> (3,‘Bob‘);
- Query OK, 3 rows affected (0.12 sec)
- Records: 3 Duplicates: 0 Warnings: 0
確認插入的表記錄數據:
- mysql> SELECT * FROM tb1;
- +----+--------+
- | id | name |
- +----+--------+
- | 1 | Jack |
- | 2 | Kenthy |
- | 3 | Bob |
- +----+--------+
- 3 rows in set (0.00 sec)
2)刪除前一步添加的3條表記錄
執行刪除所有表記錄操作:
- mysql> DELETE FROM tb1;
- Query OK, 3 rows affected (0.09 sec)
確認刪除結果:
- mysql> SELECT * FROM tb1;
- Empty set (0.00 sec)
步驟三:通過binlog日誌恢復表記錄
binlog會記錄所有的數據庫、表更改操作,所以可在必要的時候重新執行以前做過的一部分數據操作,但對於啟用binlog之前已經存在的庫、表數據將不適用。
根據上述“恢復被刪除的3條表記錄”的需求,應通過mysqlbinlog工具查看相關日誌文件,找到刪除這些表記錄的時間點,只要恢復此前的SQL操作(主要是插入那3條記錄的操作)即可。
1)查看mysql-bin.000002日誌內容
- [[email protected] ~]# mysqlbinlog /var/lib/mysql/mysql-bin.000002
- /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
- /*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
- DELIMITER /*!*/;
- # at 4
- #170412 12:05:32 server id 1 end_log_pos 123 CRC32 0x6d8c069c Start: binlog v 4, server v 5.7.17-log created 170412 12:05:32 at startup
- # Warning: this binlog is either in use or was not closed properly.
- ROLLBACK/*!*/;
- BINLOG ‘
- jKftWA8BAAAAdwAAAHsAAAABAAQANS43LjE3LWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAACMp+1YEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
- AZwGjG0=
- ‘/*!*/;
- # at 123
- #170412 12:05:32 server id 1 end_log_pos 154 CRC32 0x17f50164 Previous-GTIDs
- # [empty]
- # at 154
- #170412 12:05:59 server id 1 end_log_pos 219 CRC32 0x4ba5a976 Anonymous_GTID last_committed=0 sequence_number=1
- SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
- # at 219
- #170412 12:05:59 server id 1 end_log_pos 310 CRC32 0x5b66ae13 Query thread_id=3 exec_time=0 error_code=0
- SET TIMESTAMP=1491969959/*!*/;
- SET @@session.pseudo_thread_id=3/*!*/;
- SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
- SET @@session.sql_mode=1436549152/*!*/;
- 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=8/*!*/;
- SET @@session.lc_time_names=0/*!*/;
- SET @@session.collation_database=DEFAULT/*!*/;
- CREATE DATABASE db1
- /*!*/;
- # at 310
- #170412 12:06:23 server id 1 end_log_pos 375 CRC32 0x2967cc28 Anonymous_GTID last_committed=1 sequence_number=2
- SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
- # at 375
- #170412 12:06:23 server id 1 end_log_pos 502 CRC32 0x5de09aae Query thread_id=3 exec_time=0 error_code=0
- use `db1`/*!*/;
- SET TIMESTAMP=1491969983/*!*/;
- CREATE TABLE tb1(
- id int(4) NOT NULL,name varchar(24)
- )
- /*!*/;
- # at 502
- #170412 12:06:55 server id 1 end_log_pos 567 CRC32 0x0b8cd418 Anonymous_GTID last_committed=2 sequence_number=3
- SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
- # at 567
- #170412 12:06:55 server id 1 end_log_pos 644 CRC32 0x7e8f2fa0 Query thread_id=3 exec_time=0 error_code=0
- SET TIMESTAMP=1491970015/*!*/;
- BEGIN
- /*!*/;
- # at 644
- #170412 12:06:55 server id 1 end_log_pos 772 CRC32 0x4e3f728e Query thread_id=3 exec_time=0 error_code=0 //插入表記錄的起始時間點
- SET TIMESTAMP=1491970015/*!*/;
- INSERT INTO tb1 VALUES(1,‘Jack‘),(2,‘Kenthy‘), (3,‘Bob‘)
- /*!*/;
- # at 772
- #170412 12:06:55 server id 1 end_log_pos 803 CRC32 0x6138b21f Xid = 10
- //確認事務的時間點
- COMMIT/*!*/;
- # at 803
- #170412 12:07:24 server id 1 end_log_pos 868 CRC32 0xbef3f472 Anonymous_GTID last_committed=3 sequence_number=4
- SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
- # at 868
- #170412 12:07:24 server id 1 end_log_pos 945 CRC32 0x5684e92c Query thread_id=3 exec_time=0 error_code=0
- SET TIMESTAMP=1491970044/*!*/;
- BEGIN
- /*!*/;
- # at 945
- #170412 12:07:24 server id 1 end_log_pos 1032 CRC32 0x4c1c75fc Query thread_id=3 exec_time=0 error_code=0 //刪除表記錄的時間點
- SET TIMESTAMP=1491970044/*!*/;
- DELETE FROM tb1
- /*!*/;
- # at 1032
- #170412 12:07:24 server id 1 end_log_pos 1063 CRC32 0xccf549b2 Xid = 12
- COMMIT/*!*/;
- SET @@SESSION.GTID_NEXT= ‘AUTOMATIC‘ /* added by mysqlbinlog */ /*!*/;
- DELIMITER ;
- # End of log file
- /*!50003 SET [email protected]_COMPLETION_TYPE*/;
- /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
2) 執行指定Pos節點範圍內的sql命令恢復數據
根據上述日誌分析,只要恢復從2014.01.12 20:12:14到2014.01.12 20:13:50之間的操作即可。可通過mysqlbinlog指定時間範圍輸出,結合管道交給msyql命令執行導入重做:
- [[email protected] ~]# mysqlbinlog \
- --start-datetime="2017-04-12 12:06:55" \
- --stop-datetime="2017-04-12 12:07:23" \
- /var/lib/mysql/mysql-bin.000002 | mysql -u root -p
- Enter password: //驗證口令
3)確認恢復結果
- mysql> SELECT * FROM db1.tb1;
- +----+--------+
- | id | name |
- +----+--------+
- | 1 | Jack |
- | 2 | Kenthy |
- | 3 | Bob |
- +----+--------+
- 3 rows in set (0.00 sec)
數據備份 恢復