本次使用主要演示利用LVM实现数据快照拍摄(完全备份),锁表并且日志回滚(增量备份)。
数据库的存放架构基本如下:
架构
LVM快照只能作用于存储在LVM的数据
创建一个LV:[root@Mysql-31 ~]# lvcreate -n mylv -L 500M myvg
为该LV建立文件系统:[root@Mysql-31 /data/mysql]# mkfs -t ext4 /dev/myvg/mylv
实现挂载:[root@Mysql-31 /data/mysql]# mount /dev/myvg/mylv /d1
把mysql数据库的数据文件拷贝到d1目录下(同时在/data下创建一个软链接mysql,指向/d1目录)
创建lv
在数据库中创建一个共享锁,防止在拍摄快照期间有其他用户修改数据:mysql> flush table with read lock;
为mylv逻辑卷拍摄LVM快照:[root@Mysql-31 /d2]# lvcreate -L 500M -s -n lv-snap /dev/myvg/mylv
创建lv
回滚二进制日志,方便下一次增量备份:mysql> flush logs;
释放共享锁:mysql> unlock table;
挂载并且查看信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@Mysql-31 /data/mysql]# mount -o ro  /dev/myvg/lv-snap  /d2
[root@Mysql-31 ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/sda1 10G 4.0G 6.1G 40% /
devtmpfs 479M 0 479M 0% /dev
tmpfs 489M 0 489M 0% /dev/shm
tmpfs 489M 6.9M 482M 2% /run
tmpfs 489M 0 489M 0% /sys/fs/cgroup
/dev/sda2 10G 33M 10G 1% /data
/dev/sr0 4.3G 4.3G 0 100% /iso
tmpfs 98M 0 98M 0% /run/user/0
/dev/mapper/myvg-mylv 3.9G 439M 3.2G 12% /d1
/dev/mapper/myvg-lv--snap 3.9G 439M 3.2G 12% /d2

在进入目录后查看内容,可以发现/d2目录下存在着与/d1目录一模一样的内容,证明拍摄快照成功(只复制/d1目录下的inode等信息,并不记录具体数据)
打包/d2目录的内容到别的地方,完成备份:[root@Mysql-31 /]# tar -czf mysql-2019-9-20.tar.gz d2/
移除快照:
[root@Mysql-31 /]# umount /d2
[root@Mysql-31 /]# lvremove /dev/myvg/lv-snap

验证

停止数据库服务,删除数据库的所有数据(模仿灾难):

1
2
3
[root@Mysql-31 /data/mysql]# rm -rf *
[root@Mysql-31 /data/mysql]# ls
[root@Mysql-31 /data/mysql]#

对备份数据进行解压:

1
2
3
4
5
6
7
8
9
10
11
[root@Mysql-31 /data/mysql]# tar -xf /mysql-2019-9-20.tar.gz 
[root@Mysql-31 /data/mysql]# ls
d2
[root@Mysql-31 /data/mysql]# mv d2/* .
[root@Mysql-31 /data/mysql]# ls
auto.cnf general.log ib_logfile1 Mysql-31-relay-bin.000002 Mysql-31-relay-bin.index slow.log
BBS hello ibtmp1 Mysql-31-relay-bin.000003 mysqld.log sys
class ib_buffer_pool master.info Mysql-31-relay-bin.000004 mysql.pid
d2 ibdata1 mysql Mysql-31-relay-bin.000005 performance_schema
error.log ib_logfile0 Mysql-31-relay-bin.000001 Mysql-31-relay-bin.000006 relay-log.info
[root@Mysql-31 /data/mysql]# rm -rf d2/

启动数据库后查看数据,发现所有数据都在:
[root@Mysql-31 /data/mysql]# mysql.server start
mysql> select * from class.students;

增量备份恢复

需要恢复数据一般是由于数据库系统崩溃或者数据误删除。这种情况下,仅仅使用完全备份恢复的数据并不完整。需要使用到二进制日志。
模仿例子:
在数据库中新增加了6条数据:
创建lv
在数据库中误删除掉刚刚插入的6条数据:
mysql> delete from class.students where sid>1063;

使用二进制日志恢复插入的6条数据事务的sql语句:
[root@Mysql-31 ~]# mysqlbinlog –start-position=4773 –stop-position=6712 /log-bin/mysql-bin.000033 > /root/33.sql
注:–start-position参数为恢复6条数据的事务开始指针,–stop-position为恢复6条数据的事务结束指针
进入数据库恢复数据:

1
2
设置会话变量,临时关闭二进制日志:mysql> set session sql_log_bin=0;
恢复数据:mysql> source /root/33.sql;

自动化

使用脚本使用完全备份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@Mysql-31 ~]# cat mysql-lvm-full.sh 
#!/bin/bash

a_log="/root/mysql-bak.log"
a_dir="/backup"
data_dir="/data/mysql"
data_name=`basename $data_dir`
a_time=`date +%F-%H-%M-%S`
lvm_name="/dev/myvg/mylv"

echo "[完全备份] `date` ===================" >> $a_log
tail -1 /log-bin/mysql-bin.index >> $a_log

echo "对 $data_dir 的完全备份开始 ..."
time1=`date +%s`
cp /etc/my.cnf $a_dir/my-$a_time.cnf

mkdir -p $a_dir
mkdir -p /tmp-mysql

mysql -uroot<<EOF
system echo "已锁定表... ..."
flush table with read lock;
system lvcreate -L 500M -s -n lv-mysql-snap $lvm_name > /dev/null 2>> $a_log
flush logs;
unlock table;
system echo "快照拍摄完成,已解锁表..."
EOF
time2=`date +%s`

mount -o ro /dev/myvg/lv-mysql-snap /tmp-mysql

cd / && tar -zcf $a_dir/$data_name-$a_time.tar.gz tmp-mysql/ 2>> $a_log
cd /
umount /tmp-mysql && lvremove -f /dev/myvg/lv-mysql-snap > /dev/null 2>> $a_log && echo "快照已经成功移除"
time3=`date +%s`

echo "备份完成 用时 `expr $time3 - $time1` 秒,锁表时间 `expr $time2 - $time1` 秒"

##### 实现备份的回滚功能 ##################

num=4
count=`ls -lt $a_dir | grep "\<mysql\>" | wc -l`
if [ $count -gt $num ]
then
a_name=`ls -lt $a_dir | grep "\<mysql\>" | tail -1 | awk '{print $NF}'`
rm -rf $a_dir/$a_name
fi

count2=`ls -lt $a_dir | grep "\<my\>.*cnf$" | wc -l`
if [ $count2 -gt $num ]
then
rm -rf $a_/dir/`ls -lt $a_dir | grep "\<my\>.*cnf$" | tail -1 | awk '{print $NF}'`
fi

使用脚本实现增量备份(重新添加一份二进制日志):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@Mysql-31 ~]# cat mysql-incre.sh 
#!/bin/bash

a_log="/root/mysql-bak.log"

echo "[增量备份] `date` *******************" >> $a_log
echo "上一个日志为 `tail -1 /log-bin/mysql-bin.index`" >> $a_log

mysql -uroot<<EOF
system echo "已锁定表... ..."
flush table with read lock;
flush logs;
unlock table;
system echo "备份完成,已解锁表..."
EOF

最后更新: 2019年10月05日 10:07

原始链接: https://LiYuanSh.github.io/2019/09/20/运维实战-mysql备份-LVM/

× 请我吃糖~
打赏二维码