MariaDB數據庫備份恢復之(二): 基於LVM邏輯卷快照實現數據庫的幾乎熱備

數據庫物理備份就是拷貝數據庫數據文件,但是需要考慮的問題也有:

需要確保數據文件的時間一致性?

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邏輯捲進行數據庫備份恢復的實驗就完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章