數據庫物理備份就是拷貝數據庫數據文件,但是需要考慮的問題也有:
需要確保數據文件的時間一致性?
1.冷備:停止數據庫,實現物理備份;
但是一個真正生產數據庫不能實現離線操作,那我們就可以通過數據庫的主從複製實現;
主數據庫服務器的數據同步到從服務器,而我們在主從複製中從服務器停止數據庫是不會影響業務的,就能夠實現物理備份;備份完成從服務器上線後會自動從主服務器同步數據;這是一種理想的備份方案;
2.第二種方法是基於LVM2的快照實現數據庫的備份,可以實現幾乎熱備,
前提數據庫數據必須放置在物理捲上;
下面我們就做基於LVM2的快照實現數據庫備份的實現的實驗
一.準備工作:
1.備份所有數據庫。
[root@node1 ~]# mysqldump -A --lock-all-tables > /backup/all.sql
停止mysqld服務器:
[root@node1 ~]# service mysqld stop Shutting down MySQL.. [ OK ]
2.LVM邏輯卷構建
格式化磁盤:
[root@node1 ~]# echo -n -e "n\np\n3\n\n+10G\nt\n3\n8e\n\nw\n" |fdisk /dev/sda [root@node1 ~]# partx -a /dev/sda BLKPG: Device or resource busy error adding partition 1 BLKPG: Device or resource busy error adding partition 2 BLKPG: Device or resource busy error adding partition 3
物理卷創建: [root@node1 ~]# pvcreate /dev/sda3 Physical volume "/dev/sda3" successfully created 卷組創建: [root@node1 ~]# vgcreate myvg /dev/sda3 Volume group "myvg" successfully created 邏輯卷創建: [root@node1 ~]# lvcreate -L 5G -n mylv myvg Logical volume "mylv" created [root@node1 ~]# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert mylv myvg -wi-a----- 5.00g root vg0 -wi-ao---- 20.00g swap vg0 -wi-ao---- 2.00g usr vg0 -wi-ao---- 10.00g var vg0 -wi-ao---- 20.00g
格式化邏輯卷爲ext4文件系統:
[root@node1 ~]# mke2fs -t ext4 /dev/myvg/mylv
掛載邏輯捲到數據庫數據目錄:
[root@node1 ~]# mount /dev/myvg/mylv /mydata/data/
mysql訪問此目錄需要權限,屬主屬組更改爲mysql:
[root@node1 ~]# chown -R mysql.mysql /mydata/data/
3.初始化mysql
由於我們掛載在/mydata/data上了,原來的mysql數據文件都被隱藏了,我們需要初始化mysql;
[root@node1 root]# cd /usr/local/mysql [root@node1 mysql]# scripts/mysql_install_db --user=mysql --datadir=/mydata/data
啓動mysqld服務器:
[root@node1 mysql]# service mysqld start Starting MySQL. [ OK ]
恢復我們剛纔備份的數據庫:
[root@node1 mysql]# mysql -u root -p < /backup/all.sql Enter password: [root@node1 mysql]# 是空密碼;
登錄數據庫是拒絕的:
[root@node1 mysql]# mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
初始化安裝後我們root目錄下.my.cnf中定義的數據庫root用戶的密碼無法生效了,我們需要使用空密碼登錄數據庫,執行權限刷新操作,如下命令:
[root@node1 mysql]# mysql -uroot -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 7 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> flush privileges; Query OK, 0 rows affected (0.01 sec) MariaDB [(none)]> \q Bye
下面我們就能登錄數據庫了,我們查看恢復的情況:
[root@node1 mysql]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 8 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> use hellodb; Database changed MariaDB [hellodb]> select * from tb1; +------+ | id | +------+ | 1 | | 2 | | 22 | | 9 | | 20 | +------+ 5 rows in set (0.00 sec) MariaDB [hellodb]> \q Bye
跟上篇博客的數據是一致的,前提準備完成;
二.實現階段
假設現在數據庫是線上數據庫服務器,有許多用戶連接到數據庫執行讀寫操作,我們備份操作需要考慮的方面:
1.如果是備份單個庫,那麼要確定這個庫的引擎是InnoDB,且必須是每表的存放都是單個表空間的(innodb_file_per_table);否則,備份必須執行全庫備份。
MariaDB [(none)]> show global variables like 'innodb_file_per%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | innodb_file_per_table | ON | +-----------------------+-------+ 1 row in set (0.00 sec)
我們可以查看hellodb數據庫中的文件:
[root@node1 ~]# ls /mydata/data/hellodb/ classes.frm coc.frm courses.frm db.opt myisam_table.MYD scores.frm students.frm tb1.frm teachers.frm toc.frm v1.frm classes.ibd coc.ibd courses.ibd myisam_table.frm myisam_table.MYI scores.ibd students.ibd tb1.ibd teachers.ibd toc.ibd
我們備份hellodb這個數據庫就只需要複製這個目錄裏的所有表文件即可,但是可能會出問題,大部分環境是可以的。
2.備份之前需要鎖定表;
在生產環境中你加這個鎖可能耗時很長,因爲生產環境中有很多用戶在訪問數據庫進行讀寫操作,必須等用戶操作完成後才能加上鎖;
[root@node1 ~]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 10 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. #請求鎖定表, MariaDB [(none)]> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) #滾動二進制日誌 MariaDB [(none)]> flush logs; Query OK, 0 rows affected (0.25 sec) #查看現在使用的哪個二進制文件的哪個位置;我們可以將這個信息保存下來,以後做增量備份時就需要充這個二進制日誌文件的這個位置進行。 MariaDB [(none)]> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000009 | 365 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) #查看二進制日誌 MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 67334 | | mysql-bin.000002 | 977605 | | mysql-bin.000003 | 345 | | mysql-bin.000004 | 345 | | mysql-bin.000005 | 345 | | mysql-bin.000006 | 345 | | mysql-bin.000007 | 345 | | mysql-bin.000008 | 542426 | | mysql-bin.000009 | 365 | +------------------+-----------+ 9 rows in set (0.00 sec)
不要退出,不然就釋放了。
3.進行LVM2快照創建
實際環境中創建快照時我們需要考慮這段時間內數據的變化量大小;
我們重新開啓一個進程進行快照的創建:
[root@node1 mysql]# lvcreate -L 200M -n mydata-snap /dev/myvg/mylv -s -p r Logical volume "mydata-snap" created
4.創建完成快照後立即解鎖
接上面鎖表的操作: #進行解鎖; MariaDB [(none)]> unlock tables; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> \q Bye
至此,用戶又可以讀寫操作數據庫了;
5.現在我們就能備份了
創建目錄: [root@node1 ~]# mkdir /snap 掛載快照捲到此目錄: [root@node1 ~]# mount /dev/myvg/mydata-snap /snap/ mount: block device /dev/mapper/myvg-mydata--snap is write-protected, mounting read-only 掛載完成後查看目錄裏的文件: [root@node1 ~]# ls /snap/ aria_log.00000001 mysql mysql-bin.000007 aria_log_control mysql-bin.000001 mysql-bin.000008 hellodb mysql-bin.000002 mysql-bin.000009 ibdata1 mysql-bin.000003 mysql-bin.index ib_logfile0 mysql-bin.000004 node1.stu31.com.pid ib_logfile1 mysql-bin.000005 performance_schema multi-master.info mysql-bin.000006 test
所有的數據庫都在這裏了。
下面我們就能實現將備份好的文件同步推送到其他節點的服務器上或者同步到其他目錄:
我這裏爲了演示就只推送到/backup目錄下了,並且我只推送了一個數據庫hellodb:
[root@node1 ~]# cd /snap/ [root@node1 snap]# ls aria_log.00000001 mysql mysql-bin.000007 aria_log_control mysql-bin.000001 mysql-bin.000008 hellodb mysql-bin.000002 mysql-bin.000009 ibdata1 mysql-bin.000003 mysql-bin.index ib_logfile0 mysql-bin.000004 node1.stu31.com.pid ib_logfile1 mysql-bin.000005 performance_schema multi-master.info mysql-bin.000006 test [root@node1 snap]# rm -rf /backup/hellodb-2015-01-22-19-34-04/ [root@node1 snap]# rsync -a hellodb /backup/hellodb-`date +%F-%H-%M-%S` [root@node1 snap]# ls /backup/hellodb-2015-01-22-20-21-48/ hellodb [root@node1 snap]# ls /backup/hellodb-2015-01-22-20-21-48/hellodb/ classes.frm courses.ibd scores.frm tb1.ibd v1.frm classes.ibd db.opt scores.ibd teachers.frm coc.frm myisam_table.frm students.frm teachers.ibd coc.ibd myisam_table.MYD students.ibd toc.frm courses.frm myisam_table.MYI tb1.frm toc.ibd
備份完成了。
考慮一個問題:
如果我們備份的只是單個數據庫,而且基於二進制日誌文件去做增量備份會出現將所有庫的事件都記錄下來了,我們需要使用文本分析工具對備份的二進制文件進行篩選,篩選出屬於那個指定數據庫的事件進行導入。
6.我們進行刪除操作;
[root@node1 mysql]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 11 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> use hellodb Database changed MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | myisam_table | | scores | | students | | tb1 | | teachers | | toc | | v1 | +-------------------+ 10 rows in set (0.00 sec) #我們刪除其中一個表;刪除後我們的快照空間的文件還是包含有此表的文件。 MariaDB [hellodb]> drop table myisam_table; Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> \q Bye
對比查看數據庫和快照卷的文件可以發現:
[root@node1 mysql]# ls /mydata/data/hellodb/ classes.frm courses.frm scores.ibd tb1.ibd toc.ibd classes.ibd courses.ibd students.frm teachers.frm v1.frm coc.frm db.opt students.ibd teachers.ibd coc.ibd scores.frm tb1.frm toc.frm [root@node1 mysql]# ls /snap/hellodb/ classes.frm courses.ibd scores.frm tb1.ibd v1.frm classes.ibd db.opt scores.ibd teachers.frm coc.frm myisam_table.frm students.frm teachers.ibd coc.ibd myisam_table.MYD students.ibd toc.frm courses.frm myisam_table.MYI tb1.frm toc.ibd
快照卷還包含有myisam_table這個表的數據文件。
7.我們將快照中的文件拷貝到/backup目錄中:
[root@node1 mysql]# cp -a /snap /backup [root@node1 mysql]# ls /backup/ 20150122.sql.tgz daily increment-2015-01-22.sql all.sql hellodb-2015-01-22-20-21-48 snap bak.log hellodb-2015-01-22.sql [root@node1 mysql]# ls /backup/snap/ aria_log.00000001 mysql mysql-bin.000007 aria_log_control mysql-bin.000001 mysql-bin.000008 hellodb mysql-bin.000002 mysql-bin.000009 ibdata1 mysql-bin.000003 mysql-bin.index ib_logfile0 mysql-bin.000004 node1.stu31.com.pid ib_logfile1 mysql-bin.000005 performance_schema multi-master.info mysql-bin.000006 test
所有數據庫的文件都在這裏了,包含二進制文件;
8.假如我們繼續操作將數據庫hellodb誤刪除。
[root@node1 snap]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 12 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. #刪除hellodb數據庫 MariaDB [(none)]> drop database hellodb; Query OK, 9 rows affected (1.83 sec) MariaDB [(none)]> \q Bye
9.備份數據庫的二進制日誌文件
由於我們備份快照後,其後的修改操作我們並沒有備份,我們需要讀取二進制日誌文件,找出drop數據庫的時間點,導出刪除數據庫之前的所有二進制日誌。
[root@node1 ~]# mysqlbinlog /mydata/data/mysql-bin.000009 略… # at 558 #150122 20:29:08 server id 1 end_log_pos 645 Query thread_id=12 exec_time=2 error_code=0 SET TIMESTAMP=1421929748/*!*/; drop database hellodb /*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
可以發現時間點是558,我們將時間點爲558之前的所有操作日誌都導出到一個文件中:
[root@node1 ~]# mysqlbinlog --stop-position=558 /mydata/data/mysql-bin.000009 >/tmp/b.sql [root@node1 ~]# ls /tmp all1.sql.xz hotbackup.sql mysql.sock a.sql ks-script-t3nzeD warmbackup.sql b.sql ks-script-t3nzeD.log yum.log
10.全庫恢復操作
假如生產環境中遇到重大故障後,我們需要趕快停止數據庫,進行數據庫全庫恢復操作。
停止數據庫服務器:
[root@node1 ~]# service mysqld stop Shutting down MySQL.. [ OK ] 刪除損壞的數據庫數據文件: [root@node1 ~]# rm -rf /mydata/data/* 將快照的備份文件導入數據庫數據目錄: [root@node1 ~]# cp -a /backup/snap/* /mydata/data/ 必須保證恢復回來的數據的屬主屬組無改變: [root@node1 ~]# ls -l /mydata/data/ total 112216 -rw-rw---- 1 mysql mysql 16384 Jan 22 20:14 aria_log.00000001 -rw-rw---- 1 mysql mysql 52 Jan 22 20:14 aria_log_control drwx------ 2 mysql mysql 4096 Jan 22 20:16 hellodb -rw-rw---- 1 mysql mysql 12582912 Jan 22 20:16 ibdata1 -rw-rw---- 1 mysql mysql 50331648 Jan 22 20:16 ib_logfile0 -rw-rw---- 1 mysql mysql 50331648 Jan 22 20:13 ib_logfile1 -rw-rw---- 1 mysql mysql 0 Jan 22 20:14 multi-master.info drwx------ 2 mysql root 4096 Jan 22 20:16 mysql -rw-rw---- 1 mysql mysql 67334 Jan 22 20:13 mysql-bin.000001 -rw-rw---- 1 mysql mysql 977605 Jan 22 20:13 mysql-bin.000002 -rw-rw---- 1 mysql mysql 345 Jan 22 20:13 mysql-bin.000003 -rw-rw---- 1 mysql mysql 345 Jan 22 20:13 mysql-bin.000004 -rw-rw---- 1 mysql mysql 345 Jan 22 20:13 mysql-bin.000005 -rw-rw---- 1 mysql mysql 345 Jan 22 20:13 mysql-bin.000006 -rw-rw---- 1 mysql mysql 345 Jan 22 20:14 mysql-bin.000007 -rw-rw---- 1 mysql mysql 542426 Jan 22 20:17 mysql-bin.000008 -rw-rw---- 1 mysql mysql 365 Jan 22 20:17 mysql-bin.000009 -rw-rw---- 1 mysql mysql 171 Jan 22 20:17 mysql-bin.index -rw-rw---- 1 mysql mysql 5 Jan 22 20:14 node1.stu31.com.pid drwx------ 2 mysql mysql 4096 Jan 22 20:13 performance_schema drwx------ 2 mysql root 4096 Jan 22 20:16 test 恢復完成後啓動mysqld數據庫服務: [root@node1 ~]# service mysqld start Starting MySQL. [ OK ] [root@node1 ~]#
我們連入mysql將後續修改的數據導入進數據庫:
注意:
mysqldump做的備份,數據還原時,會產生二進制日誌,如果針對大數據量的數據庫,這種二進制日誌文件是無用的,可以不記錄,我們就需要在導入文件是臨時關閉二進制日誌記錄。
[root@node1 ~]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 4 Server version: 10.0.13-MariaDB-log Source distribution Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> use hellodb; Database changed #我們原來是刪除了myisam_table 表的。 MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | myisam_table | | scores | | students | | tb1 | | teachers | | toc | | v1 | +-------------------+ 10 rows in set (0.00 sec) #臨時關閉記錄二進制日誌文件, MariaDB [hellodb]> set session sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) #恢復從備份快照後到刪除hellodb數據庫之間的操作; MariaDB [hellodb]> source /tmp/b.sql; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Database changed Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Charset changed Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) #開啓二進制記錄文件; MariaDB [hellodb]> set session sql_log_bin=1; Query OK, 0 rows affected (0.00 sec) #可以發現myisqm_table表被刪除了,還原成功; MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | students | | tb1 | | teachers | | toc | | v1 | +-------------------+ 9 rows in set (0.00 sec) MariaDB [hellodb]> \q Bye
至此,通過LVM邏輯捲進行數據庫備份恢復的實驗就完成了。