1、在生产环境中,数据的安全性至关重要
2、任何数据的丢失都可能产生严重的后果
3、造成数据丢失的原因
物理备份:对数据库操作系统的物理文件(如数据文件、日志文件等)的备份
物理备份方法
逻辑备份:对数据库逻辑组件(如:表等数据库对象)的备份
完全备份:每次对数据库进行完整的备份
差异备份:备份自从上次完全备份之后被修改过的文件
增量备份:只有在上次完全备份或者增量备份后被修改的文件才会被备份
物理冷备
备份时数据库处于关闭状态,直接打包数据库文件
备份速度快,恢复时也是最简单的
专业备份工具mysqldump或mysqlhotcopy
mysqldump常用的逻辑备份工具
mysqlhotcopy仅拥有备份MyISAM和ARCHIVE表
启用二进制日志进行增量备份
进行增量备份,需要刷新二进制日志
第三方工具备份
免费的MySQL热备份软件Percona XtraBackup
1、是对整个数据库、数据库结构和文件结构的备份
2、保存的是备份完成时刻的数据库
3、是差异备份与增量备份的基础
4、每次对数据进行完整的备份,完全备份是增量备份的基础,完全备份保存的是备份完成时刻的数据库
5、优点:
备份与恢复操作简单方便
6、缺点
数据存在大量的重复
占用大量的备份空间
备份与恢复时间长
物理冷备份与恢复
关闭MySQL数据库
使用tar命令直接打包数据库文件夹
直接替换现有MySQL目录即可
mysqldump备份与恢复
MySQL自带的备份工具,可方便实现对MySQL的备份
可以将指定的库、表导出为SQL脚本(.sql结尾)
使用命令MySQL导入备份的数据
在MySQL中先创建库,再创建表,写入记录(用于验证)
mysql> select * from abc;
+------+----------+-------+-------+
| id | name | score | hobby |
+------+----------+-------+-------+
| NULL | zhangsan | 99 | 2 |
| NULL | wangwu | 98 | 1 |
| NULL | chenqi | 97 | 3 |
+------+----------+-------+-------+
3 rows in set (0.00 sec)
先关闭数据库服务,再打包备份
[root@server1 ~]# systemctl stop mysqld.service
[root@server1 ~]# tar zcvf /opt/mysql_all-$(date +%F).tar.gz /usr/local/mysql/data
[root@server1 ~]# cd /opt
[root@server1 opt]# ls
mysql_all-2020-12-24.tar.gz rh
将原来的数据移走到备份文件夹中,解压刚才备份的tar包到/restore目录下,再移动到mysql服务的文件夹中
[root@server1 ~]# mkdir bak #创建备份文件夹
[root@server1 ~]# mv /usr/local/mysql/data bak #将现在的数据库文件移动至备份文件夹,以模拟数据库损坏
[root@server1 ~]# mkdir restore #创建恢复文件夹
[root@server1 ~]# tar zxvf /opt/mysql_all-2020-12-24.tar.gz -C restore/ #解压打包的备份至恢复文件夹
[root@server1 data]# ls
auto.cnf ib_logfile0 mysql
ib_buffer_pool ib_logfile1 performance_schema
ibdata1 lcx sys
[root@server1 data]# pwd
/root/restore/usr/local/mysql/data
[root@server1 ~]# mv restore/usr/local/mysql/data/ /usr/local/mysql/ #将解压后的备份数据移动至数据库文件夹中
重启mysql服务,登录mysql,查看数据是否恢复
mysql> select * from lcx.abc;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.01 sec)
mysqldump -u root -p --all-databses > all-data-$(date +%F).sql ###备份所有数据库
mysqldump -u root -p -databases auth mysql > auth-mysql.sql ###备份auth和mysql库
mysqldump -u root -p auth > auth-$(data +%F).sql ###备份auth数据库
mysqldump -u root -p mysql user > mysql-user-$(date +%F).sql ###备份mysql的user表
mysqldump -u root -p -d mysql user > /tmp/desc-mysql-user.sql ###备份mysql库user表的结构
方法一:基于mysql命令恢复
[root@server1 ~]# mysqldump -u root -p lcx > test-$(date +%F).sql #使用mysqldump工具备份lcx库
Enter password: #输入密码,不显示
mysql> drop database lcx; #删除lcx库模拟数据库故障
Query OK, 1 row affected (0.00 sec)
mysql> create database test2; #建立空库
Query OK, 1 row affected (0.00 sec)
[root@server1 ~]# mysql -u root -p test2 < test-2020-12-24.sql #恢复至test2库
Enter password: #输入密码,不显示
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test2 |
+--------------------+
5 rows in set (0.00 sec)
mysql> use test2
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> show tables;
+-----------------+
| Tables_in_test2 |
+-----------------+
| abc |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from abc;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.00 sec)
方法二:source基于脚本恢复
mysql> use test2;
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> source /root/test-2020-12-24.sql; #通过.sql格式的备份文件恢复至当前库中
………………
Query OK, 3 rows affected (0.00 sec) #恢复三条记录
Records: 3 Duplicates: 0 Warnings: 0
………………
mysql> show tables;
+-----------------+
| Tables_in_test2 |
+-----------------+
| abc |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from abc;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.00 sec)
MySQL的日志文件记录了详细的操作过程,千万不能随便删
使用mysqldump进行完全备份存在的问题
备份数据中有重复数据
备份时间与恢复时间过长
MySQL增量备份是自上一次备份后增加/变化的文件或者内容
特点
没有重复数据,备份量不大,时间短
恢复需要上次完全备份及完全备份之后所有的增量备份才能恢复,而且要对所有增量备份进行逐个反推恢复
MySQL没有提供直接的增量备份方法
可通过MySQL提供的二进制日志间接实现增量备份
MySQL二进制日志对备份的意义
二进制日志保存了所有更新或者可能更新数据库的操作
二进制日志在启动MySQL服务器后开始记录,并在文件达到max_binlog_size所设置的大小或者接收到flush logs命令后重新创建新的日志文件
只需定时执行flush logs方法重新创建新的日志,生成二进制文件序列,并及时把这些日志保存到安全的地方就完成了一个时间段的增量备份
一般恢复
将所有备份的二进制日志内容全部恢复
断点恢复
基于位置恢复
数据库在某一时间点可能既有错误的操作也有正确的操作
可以基于精准的位置跳过错误的操作
基于时间点恢复
跳过某个发生错误的时间点实现数据恢复
mysqlbinlog [–no-defaults] 增量备份文件 | mysql -u 用户名 -p
恢复数据到指定位置(误操作前的位置,不要选择误操作的位置)
mysqlbinlog --stop-position=‘操作id’ 二进制日志 | mysql -u 用户名 -p密码
从指定的位置开始恢复数据(误操作后正确操作的位置,与时间节点不同,选择误操作后的第一个位置节点)
mysqlbinlog --start-position=‘操作id’ 二进制日志 | mysql -u 用户名 -p密码
mysql> select * from abc; #未恢复前状态
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.00 sec)
找出要恢复的位置
at 7079 #误操作前的位置,不要选择误操作的位置
at 7183 #误操作后正确操作的位置,与时间节点不同,选择误操作后的第一个位置节点
[root@server1 ~]# mysqlbinlog --no-defaults --stop-position='7079' /usr/local/mysql/data/mysql_bin.000002 | mysql -uroot -p123456
#根据日志文件选择恢复开始位置,路径,数据库,“--stop-datetime”换成“--stop-position”
跳过某个发生错误的时间点实现数据恢复
恢复数据到指定时间(停止错误操作的时间)
mysqlbinlog --stop-datetime=‘错误时间’ 二进制日志 | mysql -u 用户名 -p密码
#恢复数据至指定的位置(误操作开始时间)
mysqlbinlog --start-datetime=‘正确操作时间’ 二进制日志 | mysql -u 用户名 -p密码
#从指定的位置开始恢复数据(跳过误操作后指定正确操作的时间)
备份
[root@server1 ~]# mkdir -p /opt/time_sql #创建时间还原点文件夹
[root@server1 ~]# mysqldump -uroot -p test2 > /opt/time_sql/test2-$(date +%F).sql #备份test2库
Enter password:
[root@server1 ~]# vi /etc/my.cnf #数据库配置文件中添加
[mysqld] #此模块添加
log_bin=/usr/local/mysql/data/mysql_bin #开启增量备份
[root@server1 ~]# systemctl restart mysqld.service
[root@server1 ~]# ls /usr/local/mysql/data/ 查看会发现日志文件mysql_bin.00000,此时内容为空
auto.cnf ib_logfile1 mysql_bin.index
ib_buffer_pool ibtmp1 performance_schema
ibdata1 mysql sys
ib_logfile0 mysql_bin.000001 test2
[root@server1 ~]# mysqldump -uroot -p123456 test2 > /opt/test2.sql #执行一次完整备份
[root@server1 ~]# mysqladmin -uroot -p123456 flush-logs #将二进制日志更新,产生新的日志文件
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
[root@server1 ~]# ls /usr/local/mysql/data/ #查看产生第二个日志文件mysql_bin.000002
auto.cnf ib_logfile1 mysql_bin.000002 test2
ib_buffer_pool ibtmp1 mysql_bin.index
ibdata1 mysql performance_schema
ib_logfile0 mysql_bin.000001 sys
[root@server1 ~]# mysql -uroot -p123456
mysql> select * from abc;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.00 sec)
mysql> insert into abc (id,name,score) values(1,'aaa',96),(2,'bbb',95),(3,'ccc',100); #正确操作
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> delete from abc where name='zhangsan'; #删除数据,模拟错误操作
Query OK, 1 row affected (0.00 sec)
mysql> insert into abc (id,name,score) values(6,'abc',100); #正确操作
Query OK, 1 row affected (0.00 sec)
mysql> select * from abc;
+------+--------+-------+
| id | name | score |
+------+--------+-------+
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
| 1 | aaa | 96 |
| 2 | bbb | 95 |
| 3 | ccc | 100 |
| 6 | abc | 100 |
+------+--------+-------+
6 rows in set (0.00 sec)
[root@server1 ~]# mysqladmin -uroot -p123456 flush-logs; #执行日志更新
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
[root@server1 ~]# ls /usr/local/mysql/data/ #查看是否新生成的日志mysql_bin.000003,刚操作的动作不在新生成的日志文件中,在mysql_bin.000002中,可通过查看知道
auto.cnf ib_logfile1 mysql_bin.000002 sys
ib_buffer_pool ibtmp1 mysql_bin.000003 test2
ibdata1 mysql mysql_bin.index
ib_logfile0 mysql_bin.000001 performance_schema
[root@server1 ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql_bin.000002 ###查询该二进制日志内容是否正确,--base64以64为解码器,output=decode-rows输出并按行进行读取, -v显示
………………
# at 910 #操作位置
#201224 21:05:50 server id 1 end_log_pos 958 CRC32 0x1213a56a Write_rows: table id 219 flags: STMT_END_F #操作时间
### INSERT INTO `test2`.`abc` #以下为操作内容
### SET
### @1=6
### @2='abc'
### @3=100
………………
找出要恢复的时间点
201224 21:05:24 --stop-datetime #误操作的时间
201224 21:05:50 --start-datetime #正确操作的时间
进数据库可以看到没有已经误操作的状态
mysql> select * from abc;
+------+--------+-------+
| id | name | score |
+------+--------+-------+
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
| 1 | aaa | 96 |
| 2 | bbb | 95 |
| 3 | ccc | 100 |
| 6 | abc | 100 |
+------+--------+-------+
6 rows in set (0.00 sec)
mysql> source /opt/test2.sql; #恢复原先的备份
mysql> show tables;
+-----------------+
| Tables_in_test2 |
+-----------------+
| abc |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from abc; #数据已经恢复,但没有刚才操作的数据
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
+------+----------+-------+
3 rows in set (0.00 sec)
[root@server1 ~]# mysqlbinlog --no-defaults --stop-datetime='2020-12-24 21:05:24' /usr/local/mysql/data/mysql_bin.000002 | mysql -uroot -p123456 #根据日志文件选择恢复停止时间,路径,数据库
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql> select * from abc; #查看数据库可以查看恢复至误删除前的状态
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | zhangsan | 99 |
| 2 | wangwu | 98 |
| 3 | chenqi | 97 |
| 1 | aaa | 96 |
| 2 | bbb | 95 |
| 3 | ccc | 100 |
+------+----------+-------+
6 rows in set (0.00 sec)
[root@server1 ~]# mysqlbinlog --no-defaults --start-datetime='2020-12-24 21:05:50' /usr/local/mysql/data/mysql_bin.000002 | mysql -uroot -p123456 #根据日志文件选择恢复开始时间,路径,数据库
mysql: [Warning] Using a password on the command line interface can be insecure.