目录
1、数据库全备份
2、准备LVM卷
3、数据恢复到LVM卷
4、基于LVM快照备份数据
5、数据灾难恢复
6、总结
写在前面:
测试环境中已安装有mysql 5.5.36数据库,但数据目录没有存放在LVM卷,此次要演示基于LVM的数据备份和恢复,所以就把mysql的数据先迁移到LVM上再做快照卷的备份。
如果innodb表基于LVM来做备份,那事务日志文件和数据文件要在同一个LVM的逻辑卷上,因为在同一时刻我们只能对一个逻辑卷做快照,如果事务日志与数据文件不在同一卷上,那做快照后会导致事务日志的事件与真正数据中提交的事务会不一致。
1、数据库全备份
先把现有的数据利用mysqldum工具进行全备份:
[root@mariadb ~]# mysqldump -uroot -p123456 --lock-all-tables --flush-logs --events --routines --master-data=2 --all-databases > /backup/data_dir/fulldata-`date +%F` .sql
[root@mariadb ~]# ls /backup/data_dir/
fulldata-2015-04-14.sql
[root@mariadb ~]# service mysqld stop #停止mysql
2、准备LVM卷
事先准备好两个卷作为LVM的PV:
[root@mariadb ~]# fdisk -l
Disk /dev/sda: 53.7 GB, 53687091200 bytes
255 heads, 63 sectors/track, 6527 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000bf287
Device Boot Start End Blocks Id System
/dev/sda1 * 1 13 102400 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2 13 1926 15360000 83 Linux
/dev/sda3 1926 2056 1048576 82 Linux swap / Solaris
/dev/sda4 2056 6527 35916127+ 5 Extended
/dev/sda5 2056 2709 5248011 8e Linux LVM
/dev/sda6 2710 3363 5253223+ 8e Linux LVM
创建PV:
[root@mariadb ~]# pvcreate /dev/sda5 /dev/sda6
Physical volume "/dev/sda5" successfully created
Physical volume "/dev/sda6" successfully created
创建VG:
12 [root@mariadb ~]# vgcreate mygroup /dev/sda5 /dev/sda6
Volume group "mygroup" successfully created
创建LV:
[root@mariadb ~]# lvcreate -n mysqldata --size 3G mygroup #大小设置为3GB
Logical volume "mysqldata" created
格式化LV并挂载:
[root@mariadb ~]# lvdisplay #显示逻辑卷的详细信息
[root@mariadb ~]# mke2fs -t ext4 /dev/mygroup/mysqldata #格式化
[root@mariadb ~]# blkid /dev/mygroup/mysqldata #获取UUID
/dev/mygroup/mysqldata: UUID="f863e626-e34e-4207-b9cb-7fbb9c5b7f1e" TYPE="ext4"
[root@mariadb ~]# mkdir /mnt/mydata #创建挂载目录
在/etc/fstab文件中加入下边一行:
[root@mariadb ~]# vim /etc/fstab
UUID=f863e626-e34e-4207-b9cb-7fbb9c5b7f1e /mnt/mydata ext4 defaults 0 0
[root@mariadb ~]# mount -a #重新挂载
[root@mariadb ~]# mount
/dev/sda2 on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
/dev/mapper/mygroup-mysqldata on /mnt/mydata type ext4 (rw)
3、数据恢复到LVM卷
创建数据目录及权限设置:
[root@mariadb ~]# mkdir /mnt/mydata/data
[root@mariadb ~]# chown -R mysql:mysql /mnt/mydata/data
[root@mariadb ~]# vim /etc/my.cnf #修改数据目录位置
datadir = /mnt/mydata/data
[root@mariadb ~]# cd /opt/lamp/mysql55/ #切换到mysql的安装目录
初始化数据库:
[root@mariadb mysql55]# scripts/mysql_install_db --user=mysql --datadir=/mnt/mydata/data
修改datadir指向的目录:
[root@mariadb mysql55]# vim /etc/rc.d/init.d/mysqld
datadir=/mnt/mydata/data
启动mysql,很奇怪,在我没有修改mysqld脚本文件中的datadir时也能正常启动:
[root@mariadb mysql55]# service mysqld start
接入mysql,修改接入密码导入备份数据:
mysql> SET PASSWORD FOR root@localhost=PASSWORD('123456');
mysql> FLUSH PRIVILEGES;
mysql> source /backup/data_dir/fulldata-2015-04-14.sql
mysql> show databases; #数据已恢复
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb1 |
| mydb2 |
| mysql |
| performance_schema |
| test |
+--------------------+
4、备份数据库
4.1、准备备份目录
[root@mariadb mysql55]# mkdir -pv /backup/`date +%F`/{data,binlog}
#以日期命令一个目录,在内还创建data和binlog目录,分别用来存放数据和二进制日志信息
4.2、修改变量、请求全表读锁
mysql> SET GLOBAL sync_binlog=1; #设置此变量为1,让每个事件尽可能同步到二进制日志文件里,以消耗IO来尽可能确保数据一致性
mysql> SHOW MASTER STATUS; #查看二进制日志和position,此信息保存在/backup/2015-04-14/binlog的binlog.txt里
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000016 | 1068076 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
mysql> FLUSH LOGS; #刷新日志
mysql> FLUSH TABLES WITH READ LOCK; #读锁请求到后不要关闭此mysql交互界面
在innodb表中,即使是请求到了读锁,但InnoDB在后台依然可能会有事务在进行读写操作,可用"mysql> SHOW ENGINE INNODB STATUS;"查看后台进程的状态,等没有写请求后再做备份。
4.2、创建快照
以只读的方式创建一个1GB大小的快照卷data-snap:
[root@mariadb mysql55]# lvcreate --snapshot /dev/mygroup/mysqldata -n data-snap --size 1G --permission r
查看快照卷的详情(快照卷也是LV):
[root@mariadb mysql55]# lvdisplay
4.3、解除锁定
回到锁定表的mysql交互式界面,解锁:
mysql> UNLOCK TABLES;
mysql> SET GLOBAL sync_binlog=0; #此参数可以根据服务器磁盘IO的负载来调整
4.4、挂载快照卷并备份数据
[root@mariadb ~]# mount /dev/mygroup/data-snap /tmp/ #挂载快照卷
[root@mariadb ~]# ls /tmp/data/
ibdata1 ib_logfile0 ib_logfile1 mariadb.pid mydb1 mydb2 mysql performance_schema test
[root@mariadb mysql55]# cp -aR /tmp/data /backup/2015-04-14/data/ #备份数据
[root@mariadb mysql55]# ls /backup/2015-04-14/data/data/
ibdata1 ib_logfile0 ib_logfile1 mariadb.pid mydb1 mydb2 mysql performance_schema test
4.5、释放快照卷
[root@mariadb ~]# umount /tmp/
[root@mariadb ~]# lvremove /dev/mygroup/data-snap
Do you really want to remove active logical volume data-snap? [y/n]: y
Logical volume "data-snap" successfully removed
5、数据灾难恢复
破坏数据,把数据目录下的所有文件都删除:
[root@mariadb mysql55]# rm -rf /mnt/mydata/data/*
[root@mariadb mysql55]# service mysqld stop #PID文件也被删掉了,无法正常停止服务
ERROR! MySQL server PID file could not be found!
[root@mariadb mysql55]# killall mysqld
把备份数据copy到数据目录:
[root@mariadb mysql55]# cp -Ra /backup/2015-04-14/data/data/* /mnt/mydata/data/
[root@mariadb mysql55]# ll /mnt/mydata/data/ #确认各文件的权限是否为mysql
启动服务:
[root@mariadb mysql55]# service mysqld start
Starting MySQL SUCCESS!
检查数据是否已恢复:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb1 |
| mydb2 |
| mysql |
| performance_schema |
| test |
+--------------------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM mydb1.tb1;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | tom | 10 |
| 2 | jack | 20 |
| 3 | zcj | 18 |
+----+------+------+
6、总结
基于LVM的数据备份方案几乎实现了热备,只是在请求读锁时会影响线上的业务,一旦当读锁请求到,创建快照几乎是瞬间完成,快照卷创建好后就可解除锁定,而备份就像复制或归档文件一样简单。数据恢复时只需要关闭mysql进程,把备份的数据复制到相应的数据目录,确保数据目录权限正确,启用服务即可,由于是直接复制的数据文件,所以索引不用重建。