使用数据库的过程中,有多种原因造成数据的丢失:
一个合理的数据库备份方案,能够在数据丢失时,有效地恢复数据,实现数据的一致性,服务可用性,而且也需要考虑技术实现难度和有效地利用资源。
直接复制数据库文件,适用于大型数据库环境,不受存储引擎的限制,但不能恢复到不同的MySQL版本;拷贝数据,速度快,但是需要关闭MySQL服务
备份的内容是 建库、建表、更新数据等操作所执行的SQL语句(DDL,DML,DCL),适用于中小型数据库;效率相对较低,MySQL服务可正常运行。
完全备份是对整个数据库的备份、数据库结构和文件结构的备份,保存的是备份完成时刻的数据库,是增量备份的基础。
优点:备份与恢复操作简单方便,缺点是数据存在大量重复,占用大量的备份空间,备份的时间长
针对于上一次备份(无论是哪种备份):备份上一次备份后,所有发生变化的文件。
记录自上次完全数据库备份之后对数据库的更改的数据库备份。
地址:Software Downloads - Percona
它是开源免费的支持MySQL 数据库热备份的软件,它能对InnoDB和XtraDB存储引擎的数据库非阻塞地备份。它能不暂停服务创建Innodb热备份;
为MySQL做增量备份;在MySQL服务器之间做在线表迁移;使创建replication更加容易;备份mysql而不增加服务器的负载。
percona-xtrabackup-2x 版本支持MySQL5.x版本;percona-xtrabackup-8x 版本支持MySQL8.x版本
由于Oracle在2020年4月底发布的MySQL 8.0.20的变化,Percona XtraBackup 8.0,最高版本为8.0.11,与MySQL 8.0.20或更高版本,或基于它的Percona产品不兼容: Percona Server for MySQL 和 Percona XtraDB Cluster。
mysql 8.0.19 yum方式安装
Percona XtraBackup 8.0.10 yum方式安装
[root@wenzi ~]# ls
anaconda-ks.cfg mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar original-ks.cfg percona-xtrabackup-80-8.0.10-1.el7.x86_64.rpm
[root@wenzi ~]# tar -x -f mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar
[root@wenzi ~]# ls
anaconda-ks.cfg mysql-community-devel-8.0.19-1.el7.x86_64.rpm mysql-community-server-8.0.19-1.el7.x86_64.rpm
mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar mysql-community-embedded-compat-8.0.19-1.el7.x86_64.rpm mysql-community-test-8.0.19-1.el7.x86_64.rpm
mysql-community-client-8.0.19-1.el7.x86_64.rpm mysql-community-libs-8.0.19-1.el7.x86_64.rpm original-ks.cfg
mysql-community-common-8.0.19-1.el7.x86_64.rpm mysql-community-libs-compat-8.0.19-1.el7.x86_64.rpm percona-xtrabackup-80-8.0.10-1.el7.x86_64.rpm2
#提前卸载mariadb的lib包,不然会和mysql-community-libs冲突
[root@wenzi ~]# yum -y remove mariadb-libs.x86_64 1:5.5.68-1.el7
#提前安装,避免出错提示
[root@wenzi ~]# yum -y install libaio net-tools
#按照以下安装顺序
[root@wenzi ~]# rpm -ivh mysql-community-common-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-libs-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-client-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-server-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-libs-compat-8.0.19-1.el7.x86_64.rpm && yum -y install percona-xtrabackup-80-8.0.10-1.el7.x86_64.rpm
[root@wenzi ~]# systemctl enable --now mysqld
[root@wenzi ~]# grep "password" /var/log/mysqld.log
2023-09-08T17:44:30.120757Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: OYph_Xz4H:zK
mysql> alter user 'root'@'localhost' identified by 'Admin.123';
Query OK, 0 rows affected (0.01 sec)
mysql> quit
Bye
[root@wenzi ~]# echo "log_bin" >> /etc/my.cnf
[root@wenzi ~]# systemctl restart mysqld
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> create table student (id int,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student values (1,'liubei');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test.student;
+------+--------+
| id | name |
+------+--------+
| 1 | liubei |
+------+--------+
1 row in set (0.00 sec)
[root@wenzi ~]# ls /var/lib/mysql
auto.cnf ca-key.pem client-key.pem ib_logfile0 #innodb_temp mysql.sock private_key.pem server-key.pem undo_001 wenzi-bin.000002
binlog.000001 ca.pem ib_buffer_pool ib_logfile1 mysql mysql.sock.lock public_key.pem sys undo_002 wenzi-bin.index
binlog.index client-cert.pem ibdata1 ibtmp1 mysql.ibd performance_schema server-cert.pem test wenzi-bin.000001
[root@wenzi ~]# mkdir -p /data/backups
[root@wenzi ~]# xtrabackup --backup --user=root --password='Admin.123' --target-dir=/data/backups/`date +'%F-%H-%M-%S'`
[root@wenzi ~]# ls /data/backups/2023-09-09-21-05-16/
backup-my.cnf ibdata1 mysql.ibd sys undo_001 wenzi-bin.000002 xtrabackup_binlog_info xtrabackup_info xtrabackup_tablespaces
ib_buffer_pool mysql performance_schema test undo_002 wenzi-bin.index xtrabackup_checkpoints xtrabackup_logfile
#查看二进制日志文件位置
[root@wenzi ~]# cat /data/backups/2023-09-09-21-05-16/xtrabackup_binlog_info
wenzi-bin.000002 155
--target-dir=备份存储目录
--databases=要备份的数据库
--tables=要备份的实际表名称
[root@wenzi ~]# systemctl stop mysqld
[root@wenzi ~]# rm -rf /var/lib/mysql/*
[root@wenzi ~]# rm -f /var/log/mysqld.log
#还原前先进行一致性检查
[root@wenzi ~]# xtrabackup --prepare --target-dir=/data/backups/2023-09-09-21-05-16/
#恢复数据
[root@wenzi ~]# xtrabackup --copy-back --target-dir=/data/backups/2023-09-09-21-05-16/
#恢复权限
[root@wenzi ~]# chown -R mysql:mysql /var/lib/mysql
[root@wenzi ~]# systemctl start mysqld
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> select * from test.student;
+------+--------+
| id | name |
+------+--------+
| 1 | liubei |
+------+--------+
1 row in set (0.01 sec)
mysql> insert into test.student values (2,'zhaoyun');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test.student;
+------+---------+
| id | name |
+------+---------+
| 1 | liubei |
| 2 | zhaoyun |
+------+---------+
2 rows in set (0.00 sec)
第一次增量备份是基于<完整备份实验>的完整备份
[root@wenzi ~]# xtrabackup --backup -uroot -p'Admin.123' --target-dir=/data/backups/inc01 --incremental-basedir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# ls /data/backups/inc01/
backup-my.cnf ibdata1.meta mysql.ibd.meta test undo_002.delta wenzi-bin.index xtrabackup_info
ib_buffer_pool mysql performance_schema undo_001.delta undo_002.meta xtrabackup_binlog_info xtrabackup_logfile
ibdata1.delta mysql.ibd.delta sys undo_001.meta wenzi-bin.000004 xtrabackup_checkpoints xtrabackup_tablespaces
mysql> insert into test.student values (3,'guanyu');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.student;
+------+---------+
| id | name |
+------+---------+
| 1 | liubei |
| 2 | zhaoyun |
| 3 | guanyu |
+------+---------+
3 rows in set (0.00 sec)
第二次增量备份是基于第一次增量备份
多次增量备份时指定的增量备份存储目录应该不同
[root@wenzi ~]# xtrabackup --backup -uroot -p'Admin.123' --target-dir=/data/backups/inc02 --incremental-basedir=/data/backups/inc01/
[root@wenzi ~]# ls /data/backups/inc02
backup-my.cnf ibdata1.meta mysql.ibd.meta test undo_002.delta wenzi-bin.index xtrabackup_info
ib_buffer_pool mysql performance_schema undo_001.delta undo_002.meta xtrabackup_binlog_info xtrabackup_logfile
ibdata1.delta mysql.ibd.delta sys undo_001.meta wenzi-bin.000005 xtrabackup_checkpoints xtrabackup_tablespaces
[root@wenzi ~]# systemctl stop mysqld
[root@wenzi ~]# rm -rf /var/lib/mysql/*
[root@wenzi ~]# rm -f /var/log/mysqld.log
#检查一致性
#先回滚 完整备份
[root@wenzi ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backups/2023-09-09-21-05-16/
#接着回滚第一次增量备份
[root@wenzi ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backups/2023-09-09-21-05-16/ --incremental-dir=/data/backups/inc01/
#再回滚第二次增量备份
[root@wenzi ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backups/2023-09-09-21-05-16/ --incremental-dir=/data/backups/inc02/
#此时所有备份文件已合并在完整备份文件中
#开始恢复
[root@wenzi ~]# xtrabackup --copy-back --target-dir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# chown -R mysql:mysql /var/lib/mysql*
[root@wenzi ~]# systemctl start mysqld
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> select * from test.student;
+------+---------+
| id | name |
+------+---------+
| 1 | liubei |
| 2 | zhaoyun |
| 3 | guanyu |
+------+---------+
3 rows in set (0.02 sec)
mysql> update test.student set name='zhangfei' where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test.student;
+------+----------+
| id | name |
+------+----------+
| 1 | liubei |
| 2 | zhangfei |
| 3 | guanyu |
+------+----------+
3 rows in set (0.00 sec)
第一次差异备份是基于<完整备份实验>的完整备份
[root@wenzi ~]# xtrabackup --backup -uroot -p'Admin.123' --target-dir=/data/backups/cy01/ --incremental-basedir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# ls /data/backups/cy01/
backup-my.cnf ibdata1.meta mysql.ibd.meta test undo_002.delta wenzi-bin.index xtrabackup_info
ib_buffer_pool mysql performance_schema undo_001.delta undo_002.meta xtrabackup_binlog_info xtrabackup_logfile
ibdata1.delta mysql.ibd.delta sys undo_001.meta wenzi-bin.000007 xtrabackup_checkpoints xtrabackup_tablespaces
mysql> update test.student set name='huangzhong' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test.student;
+------+------------+
| id | name |
+------+------------+
| 1 | huangzhong |
| 2 | zhangfei |
| 3 | guanyu |
+------+------------+
3 rows in set (0.00 sec)
第二次差异备份是基于<完整备份实验>的完整备份
[root@wenzi ~]# xtrabackup --backup -uroot -p'Admin.123' --target-dir=/data/backups/cy02/ --incremental-basedir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# ls /data/backups/cy02/
backup-my.cnf ibdata1.meta mysql.ibd.meta test undo_002.delta wenzi-bin.index xtrabackup_info
ib_buffer_pool mysql performance_schema undo_001.delta undo_002.meta xtrabackup_binlog_info xtrabackup_logfile
ibdata1.delta mysql.ibd.delta sys undo_001.meta wenzi-bin.000008 xtrabackup_checkpoints xtrabackup_tablespaces
[root@wenzi ~]# systemctl stop mysqld
[root@wenzi ~]# rm -rf /var/lib/mysql/*
[root@wenzi ~]# rm -f /var/log/mysqld.log
[root@wenzi ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backups/2023-09-09-21-05-16/ --incremental-dir=/data/backups/cy02/
[root@wenzi ~]# xtrabackup --copy-back --target-dir=/data/backups/2023-09-09-21-05-16/
[root@wenzi ~]# chown -R mysql:mysql /var/lib/mysql*
[root@wenzi ~]# systemctl start mysqld
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> select * from test.student;
+------+------------+
| id | name |
+------+------------+
| 1 | huangzhong |
| 2 | zhangfei |
| 3 | guanyu |
+------+------------+
3 rows in set (0.00 sec)
mysqldump是MySQL数据库中用于备份和导出数据库的命令行工具。它允许你导出整个数据库或仅导出特定的表。通过使用mysqldump,你可以生成一个SQL脚本文件,该文件可以用于还原已导出的数据库
优势:自动记录日志position位置;可用性,一致性;备份时的锁表机制;
常见用法:
导出所有数据库 mysqldump -uroot -p‘密码’ -A > all.sql
导出单个数据库 mysqldump -uroot -p’密码’ test1 > test1.sql
导出多个数据库 mysqldump -uroot -p’密码’ --databases test1 test2 > 2.sql
导出单张表 mysqldump -uroot -p’密码’ mysql user > mysql.user.sql;
导出多张表 mysqldump -uroot -p’密码’ mysql user db > mysql.userdb.sql;
只导出表结构 mysqldump -uroot -p’密码’ --all-databases --no-data > all.d.sql
--single-transaction 保持数据一致性,仅限innodb引擎
--master-data=1或2 将记录binlog的日志位置与文件名并追加到文件中,2是添加注释
--flush-logs 截断日志。备份之后产生新binlog。
-R 导出存储过程和自定义函数
--triggers 导出触发器,默认启用,可用--skip-triggers禁用
–opt 等同于--add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, --disable-keys 该选项默认开启,可以用--skip-opt禁用
mysql 8.0.19 yum方式安装
此实验需要两套密码,密码一:Admin.123 密码二:aDMIN.123
[root@wenzi ~]# ls
anaconda-ks.cfg mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar original-ks.cfg
[root@wenzi ~]# tar -x -f mysql-8.0.19-1.el7.x86_64.rpm-bundle.tar && yum -y remove mariadb-libs.x86_64 1:5.5.68-1.el7 && yum -y install libaio net-tools && rpm -ivh mysql-community-common-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-libs-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-client-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-server-8.0.19-1.el7.x86_64.rpm && rpm -ivh mysql-community-libs-compat-8.0.19-1.el7.x86_64.rpm && echo "log_bin" >> /etc/my.cnf && systemctl enable --now mysqld && grep "password" /var/log/mysqld.log
[root@wenzi ~]# mysql -uroot -p'an+1PuHi6g92'
mysql> alter user 'root'@'localhost' identified by 'Admin.123';
Query OK, 0 rows affected (0.00 sec)
mysql> quit
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> create database one;
Query OK, 1 row affected (0.00 sec)
mysql> use one;
Database changed
mysql> create table emp (id int,name varchar(20));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into emp values (1,'a');
Query OK, 1 row affected (0.01 sec)
mysql> select * from one.emp;
+------+------+
| id | name |
+------+------+
| 1 | a |
+------+------+
1 row in set (0.00 sec)
mysql> quit
Bye
[root@wenzi ~]# mkdir -p /data/backups
mysqldump语句会切割一次二进制日志,产生了wenzi-bin.000003
[root@wenzi ~]# mysqldump -h localhost -uroot -p'Admin.123' -A --single-transaction --master-data=2 --flush-logs > /data/backups/`date +'%F-%H-%M-%S'`_all.sql
[root@wenzi ~]# ls /data/backups/
2023-09-10-01-46-50_all.sql
[root@wenzi ~]# vim /data/backups/2023-09-10-03-15-51_all.sql
在此次备份时产生的新日志名称为wenzi-bin.000003,新日志中POS155之前是已经备份过的,从155往后是未备份过的内容
[root@wenzi mysql]# mysqlbinlog -v wenzi-bin.000003
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#230910 4:44:19 server id 1 end_log_pos 124 CRC32 0x1fa24712 Start: binlog v 4, server v 8.0.19 created 230910 4:44:19
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
I9n8ZA8BAAAAeAAAAHwAAAABAAQAOC4wLjE5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEwANAAgAAAAABAAEAAAAYAAEGggAAAAICAgCAAAACgoKKioAEjQA
CgESR6If
'/*!*/;
# at 124 从at155开始往后都是新产生的变化,未备份过的
#230910 4:44:19 server id 1 end_log_pos 155 CRC32 0xf4f29efe Previous-GTIDs
# [empty]
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
在备份时锁表,可读不可写
mysql> insert into one.emp values (2,'b');
Query OK, 1 row affected (0.00 sec)
mysql> select * from one.emp;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
+------+------+
2 rows in set (0.00 sec)
[root@wenzi ~]# mkdir -p /data/backups/binlog/ && cp /var/lib/mysql/*bin* /data/backups/binlog/
[root@wenzi ~]# ls /data/backups/binlog/
wenzi-bin.000001 wenzi-bin.000002 wenzi-bin.000003 wenzi-bin.index
此时查看二进制日志,变动的数据存在于 binlog.000003 中
[root@wenzi ~]# mysqlbinlog -v /data/backups/binlog/wenzi-bin.000003
...
# at 361
#230910 3:31:30 server id 1 end_log_pos 403 CRC32 0x48bd867c Write_rows: table id 174 flags: STMT_END_FBINLOG '
Esj8ZBMBAAAAOAAAAGkBAAAAAK4AAAAAAAEAA29uZQADZW1wAAIDDwJQAAMBAQACA/z/ANFoIYk=
Esj8ZB4BAAAAKgAAAJMBAAAAAK4AAAAAAAEAAgAC/wACAAAAAWJ8hr1I
'/*!*/;
### INSERT INTO `one`.`emp`
### SET
### @1=2
### @2='b'...
[root@wenzi ~]# systemctl stop mysqld && rm -rf /var/lib/mysql/* && rm -f /var/log/mysqld.log
启动数据库,使用默认密码登录mysql,将密码修改为准备的第二套密码 aDMIN.123
[root@wenzi ~]# systemctl start mysqld
[root@wenzi ~]# grep "password" /var/log/mysqld.log
2023-09-09T18:27:22.298328Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: !5GHJT*dlh5e
#修改为预先准备的第二个密码
[root@wenzi ~]# mysql -uroot -p'!5GHJT*dlh5e'
mysql> alter user 'root'@'localhost' identified by 'aDMIN.123';
Query OK, 0 rows affected (0.00 sec)
将备份数据导入数据库,刷新权限,此时使用的密码为 aDMIN.123
[root@wenzi ~]# mysql -uroot -p'aDMIN.123' < /data/backups/2023-09-10-01-46-50_all.sql
[root@wenzi ~]# mysql -uroot -p'aDMIN.123' -e 'flush privileges'
登录数据库,发现密码 aDMIN.123 失效,因为原先的数据库已被恢复,应使用原密码 Admin.123。同时发现数据只恢复了备份前的数据,备份后的数据变动没有恢复成功
[root@wenzi ~]# mysql -uroot -p'aDMIN.123'
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| one |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> select * from one.emp;
+------+------+
| id | name |
+------+------+
| 1 | a |
+------+------+
1 row in set (0.00 sec)
二进制日志恢复的起始即 wenzi-bin.000003的POS155。
若后续还有新产生的日志 wenzi-bin.000004、wenzi-bin.000005......,应在全写入在命令中
mysqlbinlog /data/backups/binlog/wenzi-bin.000003 /data/backups/binlog/wenzi-bin.000004 /data/backups/binlog/wenzi-bin.000005 --start-position=155 | mysql -uroot -p'Admin.123'
[root@wenzi ~]# mysqlbinlog /data/backups/binlog/wenzi-bin.000003 --start-position=155 | mysql -uroot -p'Admin.123'
[root@wenzi ~]# mysql -uroot -p'Admin.123'
mysql> select * from one.emp;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
+------+------+
2 rows in set (0.00 sec)
备份后产生的数据变化已恢复
每次还原数据库都会增加日志的体积。但这些都是还原操作。恢复数据库的日志占用了存储空间。
mysql> set sql_log_bin =0; 关闭二进制日志
mysql> source /backup/mysqldump产生的备份.sql 导入sql文件
在配置文件中关闭二进制日志