主要内容:
MySQL索引(索引分类、创建索引)、用户及授权(创建用户并授权、查看授权、撤销授权、授权库mysql)、root密码恢复、备份、使用mysqldump进行逻辑备份、Percona
一、MySQL索引
1、基本概念
MySQL 索引(Index),是用于加速数据库查询操作的重要工具。索引通过创建数据结构(如 B-Tree、Hash 等)来存储表中某一列或多列的值,从而提高查询效率。我们可以简单理解为:它是快速查找排好序的一种数据结构。(类似于书的目录,对表中字段值进行排序)
索引类型
B-Tree 索引:
- 特点:B-Tree 索引是 MySQL 中最常用的索引类型,适用于范围查询、排序和分组操作。
- 适用场景:适用于大多数查询场景,特别是需要范围查询和排序的场景。
- 创建语法:CREATE INDEX index_name ON table_name(column_name);
Hash 索引:
- 特点:Hash 索引适用于等值查询,查询速度非常快,但不支持范围查询和排序。
- 适用场景:适用于等值查询场景,如 = 操作符。
- 创建语法:CREATE INDEX index_name ON table_name(column_name) USING HASH;
全文索引:
- 特点:全文索引用于全文搜索,适用于文本内容的搜索。
- 适用场景:适用于需要对文本内容进行搜索的场景。
- 创建语法:CREATE FULLTEXT INDEX index_name ON table_name(column_name);
空间索引:
- 特点:空间索引用于地理空间数据的查询,如地理位置的搜索。
- 适用场景:适用于地理空间数据的查询场景。
- 创建语法:CREATE SPATIAL INDEX index_name ON table_name(column_name);
优点:
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性,可以大大提高MySQL的检索速度;
- 索引大大减小了服务器需要扫描的数据量;
- 索引可以帮助服务器避免排序和临时表;
- 索引可以将随机IO变成顺序IO;
缺点:
- 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL的索引也要动态的调整,不仅要保存数据,还要保存索引文件,降低了数据的维护速度;
- 建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果在一个大表上创建了多种组合索引,索引文件会膨胀很快;
- 如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果;
- 对于非常小的表,大部分情况下简单的全表扫描更高效;
2、索引分类
① 普通索引
- 不应用任何限制条件的索引,该索引可以在任何数据类型中创建。
- 字段本身的约束条件可以判断其值是否为空或唯一。
- 创建该类型索引后,用户在查询时,便可以通过索引进行查询。
② 唯一性索引
- 使用UNIQUE参数可以设置唯一索引。
- 创建该索引时,索引的值必须唯一,通过唯一索引,用户可以快速定位某条记录
- 主键也是一种特殊的唯一索引。
链接:https://blog.csdn.net/qq_34793133/article/details/81712909
③ 全文索引
- 使用FULLTEXT参数可以设置索引为全文索引。
- 全文索引只能创建在CHAR、VARCHAR或者TEXT类型的字段上。查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。
- 在默认情况下,应用全文搜索大小写不敏感。如果索引的列使用二进制排序后,可以执行大小写敏感的全文索引。
④ 单列索引
- 顾名思义,单列索引即只对应一个字段的索引。
- 应用该索引的条件只需要保证该索引值对应一个字段即可。
- 可以包括普通、唯一、全文索引
⑤ 多列索引
- 多列索引是在表的多个字段上创建一个索引。
- 该索引指向创建时对应的多个字段,用户可以通过这几个字段进行查询。
- 要想应用该索引,用户必须使用这些字段中的第一个字段。
3、普通索引index
使用规则:
① 一个表中可以有多个Index字段
② 字段的值允许重复,且可以赋Null值
③ 通常把它作为where查询条件的字段设置为Index字段(例如where “index字段”)
④ index索引字段的标志为 MUL
1)创建索引
方法1:创建表时创建索引
- 语法格式:
CREATE TABLE 表名(
字段列表,
index(字段名),
index(字段名),
);
方法2:在已有的表里创建索引
- 语法格式:CREATE INDEX 索引名 ON 表名(字段名);
2)查看索引
- 语法格式:
DESC 表名; //注意观察Key这一列
SHOW INDEX FROM 表名 \G
3)删除索引
- 语法格式:DROP INDEX 索引名 ON 库.表名;
例如:在已有的表里创建索引
mysql> create index index_birth on employees(birth_date);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc employees; // index索引字段的标志为MUL
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| employee_id | int(6) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
| hire_date | date | YES | | NULL | |
| birth_date | date | YES | MUL | NULL | |
| email | varchar(25) | YES | | NULL | |
| phone_number | char(11) | YES | | NULL | |
| dept_id | int(4) | YES | MUL | NULL | |
+--------------+-------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
例如:查看数据表中已创建的索引
mysql> show index from employees\G
*************************** 1. row ***************************
Table: employees
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: employee_id
Collation: A
Cardinality: 133
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: employees
Non_unique: 1
Key_name: dept_id_fk
Seq_in_index: 1
Column_name: dept_id
Collation: A
Cardinality: 8
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
*************************** 3. row ***************************
Table: employees
Non_unique: 1
Key_name: index_birth
Seq_in_index: 1
Column_name: birth_date
Collation: A
Cardinality: 132
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
3 rows in set (0.00 sec)
二、用户及授权
1、创建用户并授权
- 语法格式:GRANT 权限列表 ON 库名.表名 TO '用户名'@'客户端地址' IDENTIFIED BY '密码' [WITH GRANT OPTION];
解释说明:
- 权限列表:用户的操作权限,如`SELECT`,`INSERT`,`UPDATE`,`DELETE`等,如果要授予所有权限则使用【ALL】
- 表名:如果要授予该用户对所有数据库和表的相应操作权限则可用【*】表示,如【*.*】
- 用户名:将授予库.表的权限指定的用户,若用户不存在则自动创建;
- 客户端地址:如果是本机登录可写localhost,如果是任意地址登录可写【%】(不建议)
- WITH GRANT OPTION:赋予权限的用户还拥有授权权限;
2、客户端远程连接数据库
- 语法格式:mysql -h服务器 -u用户名 -p密码 //需提前安装mysql/mariadb客户端
例如1:授予anj用户在本地登陆的权限
mysql> grant select,insert,update(phone_number,email) on nsd2021.employees
-> to anj@'localhost' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 登录另外一台主机访问数据库服务器(该主机使用Mariadb客户端)
[root@client ~]# mysql -uanj -pNSD2021@tedu.cn -h192.168.2.5 //授权地址是localhost
ERROR 1045 (28000): Access denied for user 'anj'@'gateway' (using password: YES)
[root@client ~]# ssh 192.168.2.5 //远程访问192.168.2.5服务器方式,本地登录数据库
[root@localhost ~]# mysql -uanj -pNSD2021@tedu.cn
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> exit
例如2:授予anj用户在任意地址登陆的权限
mysql> grant select,insert,update(phone_number,email) on nsd2021.employees
-> to anj@'%' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 登录另一台主机访问数据库服务器(该主机使用Mariadb客户端)
[root@client ~]# mysql -uanj -pNSD2021@tedu.cn -h192.168.2.5 //授权地址是%任意
Welcome to the MariaDB monitor. Commands end with ; or \g.
MySQL [(none)]>
# 测试SELECT权限
MySQL [(none)]> use nsd2021;
MySQL [nsd2021]> show tables; //仅授予SELECT查nsd2021库employess表的权限;
+-------------------+
| Tables_in_nsd2021 |
+-------------------+
| employees |
+-------------------+
1 row in set (0.00 sec)
MySQL [nsd2021]> select * from departments where dept_id=1; //无法查看其它表
ERROR 1142 (42000): SELECT command denied to user 'anj'@'192.168.2.6' for table 'departments'
MySQL [nsd2021]> select * from employees where employee_id=3;
+-------------+-----------+------------+------------+------------------+--------------+---------+
| employee_id | name | hire_date | birth_date | email | phone_number | dept_id |
+-------------+-----------+------------+------------+------------------+--------------+---------+
| 3 | 李玉英 | 2012-01-19 | 1974-01-25 | liyuying@tedu.cn | 15628557234 | 1 |
+-------------+-----------+------------+------------+------------------+--------------+---------+
1 row in set (0.00 sec)
# 测试INSERT权限
MySQL [nsd2021]> insert into employees (name) values ('张三'); //可执行INSERT插入
Query OK, 1 row affected (0.00 sec)
MySQL [nsd2021]> select * from employees where name=”张三”;
+-------------+--------+-----------+------------+---------------+--------------+---------+
| employee_id | name | hire_date | birth_date | email | phone_number | dept_id |
+-------------+--------+-----------+------------+---------------+--------------+---------+
| 134 | 张三 | NULL | NULL | NULL | NULL | NULL |
+-------------+--------+-----------+------------+---------------+--------------+---------+
1 row in set (0.00 sec)
# 测试UPDATE权限(仅允许更新phone_number和email字段)
MySQL [nsd2021]> update employees set phone_number=13912342234,email='test@tedu.com' where name='张三';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL [nsd2021]> select * from employees where name='张三';
+-------------+--------+-----------+------------+---------------+--------------+---------+
| employee_id | name | hire_date | birth_date | email | phone_number | dept_id |
+-------------+--------+-----------+------------+---------------+--------------+---------+
| 134 | 张三 | NULL | NULL | test@tedu.com | 13912342234 | NULL |
+-------------+--------+-----------+------------+---------------+--------------+---------+
1 row in set (0.00 sec)
# 测试DELETE权限
MySQL [nsd2021]> delete from employees where name='张三'; //拒绝执行DELETE删除
ERROR 1142 (42000): DELETE command denied to user 'anj'@'192.168.2.6' for table 'employees'
3、相关查询权限指令
① 查看用户信息
- 格式:SELECT USER();
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
② 显示当前登陆用户的权限
- 格式:SHOW GRANTS;
mysql> show grants;
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
③ 管理员查看指定用户的权限,用户不存在则报错
- 格式:SHOW GRANTS FOR 用户名@'客户端地址';
注意:如果创建并授权同一个用户有两条权限记录,权限会叠加,不会覆盖;
mysql> show grants for anj@'%';
+------------------------------------------------------------------------------------------+
| Grants for anj@% |
+------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'anj'@'%' |
| GRANT SELECT, INSERT, UPDATE (email, phone_number) ON `nsd2021`.`employees` TO 'anj'@'%' |
+------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> show grants for anj@'localhost';
+--------------------------------------------------------------------------------------------------+
| Grants for anj@localhost |
+--------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'anj'@'localhost' |
| GRANT SELECT, INSERT, UPDATE (email, phone_number) ON `nsd2021`.`employees` TO 'anj'@'localhost' |
+--------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
④ 修改用户自己的密码
- 格式:SET PASSWORD=PASSWORD('密码');
- 补充:password(),即函数
- 补充:按向上箭头无法显示修改密码的历史记录(敏感数据)
mysql> set password=password('NSD2021@tedu.cn');
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> select password('NSD2021@tedu.cn');
+-------------------------------------------+
| password('NSD2021@tedu.cn') |
+-------------------------------------------+
| *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
+-------------------------------------------+
1 row in set, 1 warning (0.00 sec)
⑤ 管理员修改指定用户密码
- 格式:SET PASSWORD FOR 用户名@'客户端地址'=PASSWORD('密码');
mysql> set password for jerry@'%'=password('NSD2021@tedu.cn');
Query OK, 0 rows affected, 1 warning (0.00 sec)
⑥ 删除授权用户
- 格式:DROP USER 用户名@'客户端地址';
mysql> drop user anj@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> drop user anj@'localhost';
Query OK, 0 rows affected (0.00 sec)
4、授权库mysql
授权库mysql常用记录相关授权的表(内部数据库mysql)
- user:记录已有的授权用户及权限(主要字段:User、Host)
- db:记录已有授权用户对数据库的访问权限(主要字段:User、Host、Db)
- tables_priv:记录已有授权用户对表的访问权限
- columns_priv:记录已有授权用户对字段的访问权限
授权库查询访问权限步骤示例:
mysql> grant select,insert,update(phone_number,email) on nsd2021.employees
-> to anj@'localhost' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.00 sec)
① 查看已有的授权用户及权限
mysql> select host,user from mysql.user;
+-----------+-----------+
| host | user |
+-----------+-----------+
| % | root |
| localhost | anj |
| localhost | mysql.sys |
| localhost | root |
+-----------+-----------+
7 rows in set (0.00 sec)
② 查看已有授权用户对数据库的访问权限
mysql> select host,user,db from mysql.db where user='anj';
Empty set (0.00 sec)
③ 查看已有授权用户对表的访问权限
mysql> select * from tables_priv where User like '%anj%'\G
*************************** 1. row ***************************
Host: localhost
Db: nsd2021
User: anj
Table_name: employees
Grantor: root@localhost
Timestamp: 0000-00-00 00:00:00
Table_priv: Select,Insert
Column_priv: Update
1 row in set (0.00 sec)
④ 查看已有授权用户对字段的访问权限
mysql> select * from columns_priv where User like '%anj%'\G
*************************** 1. row ***************************
Host: localhost
Db: nsd2021
User: anj
Table_name: employees
Column_name: email
Timestamp: 0000-00-00 00:00:00
Column_priv: Update
*************************** 2. row ***************************
Host: localhost
Db: nsd2021
User: anj
Table_name: employees
Column_name: phone_number
Timestamp: 0000-00-00 00:00:00
Column_priv: Update
2 rows in set (0.00 sec)
⑤ 查看指定用户的权限
mysql> show grants for anj@'localhost';
+--------------------------------------------------------------------------------------------------+
| Grants for anj@localhost |
+--------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'anj'@'localhost' |
| GRANT SELECT, INSERT, UPDATE (email, phone_number) ON `nsd2021`.`employees` TO 'anj'@'localhost' |
+--------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> show grants for anj@'localhost'\G
*************************** 1. row ***************************
Grants for anj@localhost: GRANT USAGE ON *.* TO 'anj'@'localhost'
*************************** 2. row ***************************
Grants for anj@localhost: GRANT SELECT, INSERT, UPDATE (email, phone_number) ON `nsd2021`.`employees` TO 'anj'@'localhost'
2 rows in set (0.00 sec)
5、撤销用户权限(REVOKE)
- 语法格式:REVOKE 权限列表 ON 库名.表名 FROM 用户名@'客户端地址';
① 撤回代理授权权限
- 格式:REVOKE GRANT OPTION ON *.* FROM 用户名@'客户端地址';
② 撤回用户删除权限
- 格式:REVOKE DELETE ON *.* FROM 用户名@'客户端地址';
③ 撤回所有权限
- 格式:REVOKE ALL ON *.* FROM 用户名@'客户端地址';
例如1:撤回anj用户的insert权限
mysql> revoke insert on nsd2021.employees from anj@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for anj@'localhost';
+------------------------------------------------------------------------------------------+
| Grants for anj@localhost |
+------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'anj'@'localhost' |
| GRANT SELECT, UPDATE (email, phone_number) ON `nsd2021`.`employees` TO 'anj'@'localhost' |
+------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
例如2:创建tom用户并授予代理授权权限
mysql> grant all on *.* to tom@'%' identified by 'NSD2021@tedu.cn' with grant option;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show grants for tom@'%';
+------------------------------------------------------------+
| Grants for tom@% |
+------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'tom'@'%' WITH GRANT OPTION |
+------------------------------------------------------------+
1 row in set (0.00 sec)
# 登录另一台主机,使用tom用户访问数据库,并创建授权jerry用户
[root@client ~]# mysql -utom -pNSD2021@tedu.cn -h192.168.2.5
MySQL [(none)]> grant select on nsd2021.* to jerry@'%' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 撤回tom用户的grant option代理授予权限
mysql> revoke grant option on *.* from tom@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for tom@'%';
+------------------------------------------+
| Grants for tom@% |
+------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'tom'@'%' |
+------------------------------------------+
1 row in set (0.00 sec)
# 登录另一台主机,使用tom用户访问数据库,并测试创建授权jerry用户效果
MySQL [(none)]> grant select on nsd2021.* to jim@'%' identified by 'NSD2021@tedu.cn';
ERROR 1044 (42000): Access denied for user 'tom'@'%' to database 'nsd2021'
例如3:撤回tom用户的所有权限
mysql> revoke all on *.* from tom@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for tom@'%';
+---------------------------------+
| Grants for tom@% |
+---------------------------------+
| GRANT USAGE ON *.* TO 'tom'@'%' |
+---------------------------------+
1 row in set (0.00 sec)
6、root密码恢复
恢复密码步骤:
① 停止MySQL服务
② 跳过授权表,并启动MySQL服务程序
③ 修改数据库root密码(authentication_string认证字符串)
④ 以正常方式重启MySQL服务程序
root密码恢复示例:
步骤1:停止MySQL服务
[root@localhost ~]# systemctl stop mysqld //关闭服务
步骤2:修改配置文件,并启动MySQL服务程序
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
skip-grant-tables //跳过授权表
[root@localhost ~]# systemctl start mysqld //启动服务
步骤3:修改数据库root密码
[root@localhost ~]# mysql
mysql> select user,host,authentication_string from mysql.user; //查看认证字符串(加密密码)
+-----------+-----------+-------------------------------------------+
| user | host | authentication_string |
+-----------+-----------+-------------------------------------------+
| root | localhost | *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
| mysql.sys | localhost | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| tom | % | *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
| root | % | *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
| anj | localhost | *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
| jerry | % | *2EE7382F92B1F44D0DA9DBE20FE0078A1D370C49 |
+-----------+-----------+-------------------------------------------+
6 rows in set (0.00 sec)
mysql> update mysql.user set authentication_string=password('123456')
-> where user='root' and host='localhost'; //不筛选条件则更新所有记录的密码
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> flush privileges; //刷新权限
Query OK, 0 rows affected (0.00 sec)
步骤4:以正常方式重启MySQL服务程序
[root@localhost ~]# systemctl stop mysqld
[root@localhost ~]# vim /etc/my.cnf
# skip-grant-tables //注释跳过授权表
[root@localhost ~]# systemctl start mysqld
[root@localhost ~]# mysql -uroot -p123456 //测试新密码登录访问数据库
mysql>
补充:当mysql 新设置用户或更改密码后需用flush privileges刷新MySQL的系统权限相关表,否则会出现拒绝访问;还有一种方法,就是重新启动mysql服务器,来使新设置生效。
三、数据库备份/还原
(物理备份、完全备份、差异备份、增量备份)
1、物理备份
备份方法:拷贝/var/lib/mysql数据库目录,存放到目标主机即可;
补充:若要还原新的数据库,可直接删除/var/lib/mysql数据库目录,再重启mysql服务
注意:无论备份还是恢复,都要验证用户权限!
物理备份步骤示例:
步骤1:准备两台虚拟机,并安装mysql服务(192.168.2.5和192.168.2.10)
[root@localhost ~]# scp /etc/yum.repos.d/mysql.repo 192.168.2.10:/etc/yum.repos.d/
[root@node10 ~]# yum -y install mysql-community* //安装mysql服务,但不启动服务
步骤2:源主机192.168.2.5操作
① 停止数据库服务(服务需要停止,数据才不会继续更新)
[root@localhost ~]# systemctl stop mysqld
② 拷贝/var/lib/mysql数据库目录,到目标主机;拷贝完成后再启动服务
[root@localhost ~]# scp -r /var/lib/mysql root@192.168.2.10:/var/lib/mysql
[root@localhost ~]# systemctl start mysqld
步骤3:目标主机192.168.2.10操作
[root@node10 ~]# useradd mysql //创建mysql用户
[root@node10 ~]# chown -R mysql:mysql /var/lib/mysql //修改文件属主:属组权限
[root@node10 ~]# syscteml start mysqld //启动数据库服务
步骤4:测试数据库连接
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| nsd2021 |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
1.1、使用mysqldump进行逻辑备份
- 备份所有数据:
① 完全备份:备份所有数据(单一或多个库、单一或多张表、整个数据库)
- 只备份更新数据:
② 差异备份:备份自完全备份后产生的数据(完全备份+差异备份)
③ 增量备份:备份自上次备份之后产生的数据(完全备份+增量备份)
- 补充:使用差异备份适合存储容量充足的场景,首次备份都是先完全备份,后续再进行差异备份(自完全备份后产生的数据);若要还原数据,只需要还原最终备份的那一次;
- 补充:使用增量备份适合存储容量小、数据小的场景,首次备份也是先完全备份,后续再进行增量备份(自上一次备份之后产生的数据);若要还原数据,需要还原每一次的备份;
- 注意:无论备份还是恢复,都要验证用户权限!
2、完全备份
备份命令
- 语法格式:mysqldump -u用户名 -p密码 > 路径/文件名.sql
恢复命令(导入数据库)
- 语法格式:mysql -u用户名 -p密码 < 路径/备份文件名.sql
完全备份示例:
1)备份所有库
- 格式:mysqldump -u用户 -p密码 –all-databases > 路径/文件名.sql
- 格式:mysqldump -u用户 -p密码 -A > 路径/文件名.sql
步骤1:源数据库192.168.2.5操作
[root@localhost ~]# mkdir /root/dbbackup //手动创建备份目录
方法1:
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn --all-databases > dbbackup/alldb.sql
方法2:
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn -A > dbbackup/alldb.sql
补充:备份的sql文件中有建库和删表、建表操作来完成完全备份,其中LOCK WRITE代表写锁,防止在同一时间去写入数据时发生冲突;先进行写操作的先写;
# 拷贝文件到目标服务器
[root@localhost ~]# scp -r /root/dbbackup root@192.168.2.10:/root/
步骤2:目标数据库192.168.2.10进行恢复操作
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn < /root/dbbackup/alldb.sql
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| nsd2021 |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
2)备份某个库(包括库里的所有表)
- 格式:mysqldump -u用户 -p密码 数据库 > 路径/文件名.sql
步骤1:源数据库192.168.2.5操作
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn nsd2021 > dbbackup/tedu_db.sql
补充:备份的sql文件中有删表和建表操作来完成完全备份
# 拷贝文件到目标服务器
[root@localhost ~]# scp -r /root/dbbackup/ root@192.168.2.10:/root/
步骤2:目标数据库192.168.2.10进行恢复操作
mysql> drop database nsd2021; //删除库,以便测试结果
mysql> create database nsd2021 default charset utf8mb4; //创建数据库
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn nsd2021 < /root/dbbackup/tedu_db.sql
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| nsd2021 |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
3)备份某一张表
- 格式:mysqldump -u用户 -p密码 数据库 数据表 > 路径/文件名.sql
步骤1:源数据库192.168.2.5操作
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn nsd2021 salary > dbbackup/nsd2021_salary.sql
补充:备份的sql文件中有删salary表和建salary表操作来完成完全备份
# 拷贝文件到目标服务器
[root@localhost ~]# scp -r dbbackup/ root@192.168.2.10:/root/
步骤2:目标数据库192.168.2.10进行恢复操作
mysql> truncate salary; // 清空表,以便测试结果
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn nsd2021 < /root/dbbackup/nsd2021_salary.sql
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select count(*) from nsd2021.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)
4)备份多个库
- 格式:mysqldump -u用户 -p密码 -B 数据库1 数据库2 > 路径/文件名.sql
步骤1:源数据库192.168.2.5操作
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn -B nsd2021 mysql > dbbackup/twodb.sql
补充:备份的sql文件中有建库和多个删表、建表操作来完成完全备份
# 拷贝文件到目标服务器
[root@localhost ~]# scp -r dbbackup/ root@192.168.2.10:/root/
步骤2:目标数据库192.168.2.10进行恢复操作
mysql> drop database nsd2021; //删除库,以便测试结果
mysql> drop database mysql;
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn < /root/dbbackup/twodb.sql
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| nsd2021 |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
5)备份多张表
- 格式:mysqldump -u用户 -p密码 数据库 数据表1 数据表2 > 路径/文件名.sql
步骤1:源数据库192.168.2.5操作
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn nsd2021 employees salary > dbbackup/nsd2021_employees_salary.sql
# 拷贝文件到目标服务器
[root@localhost ~]# scp -r dbbackup/ root@192.168.2.10:/root/
步骤2:目标数据库192.168.2.10进行恢复操作
mysql> truncate salary; //清空表,以便测试结果
mysql> delete from employees;
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn nsd2021 < /root/dbbackup/nsd2021_employees_salary.sql
mysql> select count(*) from nsd2021.employees;
+----------+
| count(*) |
+----------+
| 134 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from nsd2021.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)
3、增量备份
binlog日志概述
- binlog日志(二进制日志),是MySQL服务日志文件的一种,默认没有启用;
- 记录除查询之外的所有SQL命令(对数据库造成影响的SQL命令);
- 可用于数据的备份和恢复(增量备份);(原理:即恢复数据时,执行日志文件记录的SQL语句)
- 它是MySQL主从同步的必要条件;
- 修改/etc/my.cnf主配置文件来启用binlog日志文件
配置项 | 用途 |
server_id=数字 | 指定服务器id值(1-255) |
log-bin 或 log_bin=目录/文件名 | 启用binlog日志,不指定默认存放在/var/lib/mysql |
max_binlog_size=数值m | 日志文件容量,默认1GB |
注意:无论备份还是恢复,都要验证用户权限!
1)启用binlog日志示例:
mysql> show master status; //列出binlog日志偏移点位(Position)信息
Empty set (0.00 sec) //未开启日志为空
① 修改数据库主配置文件
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
server_id = 5 //指定服务器id
log_bin //启用binlog日志(不指定目录默认存放在/var/lib/mysql)
…
[root@localhost ~]# systemctl restart mysqld //重启服务
② 测试
通过MySQL查看binlog日志偏移点位信息
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| localhost-bin.000001 | 154 | | | |
+----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
- 查看保存日志的目录(以主机名命名的-bin.000001日志文件和-bin..index文件)
[root@localhost ~]# ls /var/lib/mysql/localhost-bin.*
/var/lib/mysql/localhost-bin.000001 /var/lib/mysql/localhost-bin.index
[root@localhost ~]# cat /var/lib/mysql/localhost-bin.index
./localhost-bin.000001
补充:binlog日志文件名的命名默认会加编号(例如:文件-000001),当超过日志文件容量默认1GB时,自动创建第二个日志文件(例如:文件-000002)
补充:bin..index文件用来存放已存在的binlog日志文件;
2)手动创建binlog日志文件示例:
binlog文件默认存在/var/lib/mysql目录下,也可手动进行制定binlog日志存放目录和文件名;
① 创建用于保存日志文件的目录
[root@localhost ~]# mkdir /mybinlog
[root@localhost ~]# chown mysql:mysql /mybinlog/
② 修改数据库主配置文件
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
server_id = 5
log_bin = /mybinlog/mylog //指定存放日志的目录/文件名
…
[root@localhost ~]# systemctl restart mysqld //重启服务
③ 测试
通过MySQL查看binlog日志偏移点位信息
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000001 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
查看创建的保存日志目录
[root@localhost ~]# ls /mybinlog/
mylog.000001 mylog.index
3)新建binlog日志文件示例:
① 方法1:重启mysql服务
[root@localhost ~]# systemctl restart mysqld
[root@localhost ~]# ls /mybinlog/
mylog.000001 mylog.000002 mylog.index
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000002 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
② 方法2:flush指令
mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000003 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@localhost ~]# ls /mybinlog/
mylog.000001 mylog.000002 mylog.000003 mylog.index
③ 方法3:备份时刷新日志
[root@localhost ~]# mysqldump -uroot -pNSD2021@tedu.cn --flush-logs nsd2021 > dbbackup/nsd2021_full.sql
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000004 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@localhost ~]# ls /mybinlog/
mylog.000001 mylog.000002 mylog.000003 mylog.000004 mylog.index
[root@localhost ~]# cat /mybinlog/mylog.index
/mybinlog/mylog.000001
/mybinlog/mylog.000002
/mybinlog/mylog.000003
/mybinlog/mylog.000004
4)删除已有的binlog日志
① 删除指定编号之前的日志文件
- 格式:purge master logs to "日志文件名.编号";
注意:删除指定日志文件编号之前的日志,不包含本身;
注意:尽量使用MySQL的purge命令去删除日志,rm删除无法删除数据库内部关系
例如:删除mylog.000003(不包含)之前的日志
mysql> purge master logs to "mylog.000003";
Query OK, 0 rows affected (0.00 sec)
[root@localhost ~]# ls /mybinlog/ //查看目录下剩余的日志文件
mylog.000003 mylog.000004 mylog.index
[root@localhost ~]# cat /mybinlog/mylog.index
/mybinlog/mylog.000003
/mybinlog/mylog.000004
② 删除所有日志,并重新启用新日志
- 格式:reset master //立刻删除谨慎操作
mysql> reset master;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000001 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@localhost ~]# ls /mybinlog/ //查看目录下剩余的日志文件
mylog.000001 mylog.index
5)通过binlog日志修改数据库示例:
通过mysqlbinlog命令,以明文的方式查看binlog日志内容;
- 格式:mysqlbinlog /Binlog日志文件.编号 | mysql -uroot -p密码
步骤1:源服务器192.168.2.5进行插入操作
补充:需先开启binlog日志,且进行除select外的SQL语句操作才能被记录;
① 查看binlog日志的偏移点位信息
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000001 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
② 向departments表中插入数据
mysql> insert into departments(dept_name) values ('store1'),('store2'),('store3');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 37 | store1 |
| 38 | store2 |
| 39 | store3 |
+---------+-----------+
35 rows in set (0.00 sec)
③ 再次查看binlog日志的偏移点位信息变化
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000001 | 458 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
④ 查看binlog日志内容
[root@localhost ~]# mysqlbinlog /mybinlog/mylog.000001
扩展:可通过echo 'BINLOG内容' | base64 –decode 简单查看base64格式里的内容
⑤ 将binlog日志拷贝到目标主机
[root@localhost ~]# scp -r /mybinlog/ 192.168.2.10:/root
root@192.168.2.10's password:
mylog.000001 100% 458 670.0KB/s 00:00
mylog.index 100% 23 57.3KB/s 00:00
步骤2:在目标主机192.168.2.10上通过binlog同步源主机上的数据
[root@node10 ~]# ls /root/mybinlog/
mylog.000001 mylog.index
[root@node10 ~]# mysqlbinlog /root/mybinlog/mylog.000001 | mysql -uroot -pNSD2021@tedu.cn
验证:
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from nsd2021.departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 37 | store1 |
| 38 | store2 |
| 39 | store3 |
+---------+-----------+
35 rows in set (0.00 sec)
补充:通过binlog同步源主机上的数据,原理:查看并执行binlog日志中记录的所有对数据库产生影响的SQL语句,来实现数据的还原操作;实现增量备份,则执行不同的binlog日志文件达到效果;
6)修改binlog记录格式示例:
binlog日记记录方式
① row:行模式(默认模式),不记录SQL语句上下文相关信息,仅保存哪条记录被修改
② statement:陈述模式(易读),每一条会修改数据的SQL语句都会记录在Binlog中
③ mixed:混合模式(row+statement),以上两种的混合使用
- 命令:show variables like 'binlog_format'; //通过MySQL查看binlog日记记录方式
步骤1:查看当前binlog日记记录方式
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
步骤2:修改日志记录格式
[root@localhost ~]# vim /etc/my.cnf //修改数据库主配置文件
[mysqld]
server_id = 5
log_bin = /mybinlog/mylog
binlog_format = 'mixed' //修改日志记录格式为混合模式
[root@localhost ~]# systemctl restart mysqld //重启服务
步骤3:查看binlog日志信息并修改数据
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> show master status; //因服务重启,binlog日志文件已更新
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000002 | 154 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> use nsd2021;
mysql> insert into departments(dept_name) values('store4'),('store5');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
步骤4:查看日志
[root@localhost ~]# mysqlbinlog /mybinlog/mylog.000002
7)通过binlog日志指定范围内的数据进行恢复
- 格式:mysqlbinlog --start-position=起始 --stop-position=结束 /Binlog日志文件.编号 | mysql -uroot -p密码
步骤1:源主机192.168.2.5进行删除操作(使binlog日志记录删除SQL语句)
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> delete from nsd2021.departments where dept_name like 'store%';
Query OK, 5 rows affected (0.01 sec)
mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| mylog.000002 | 791 | | | |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# 拷贝日志文件到目标服务器
[root@localhost ~]# scp -r /mybinlog/ root@192.168.2.10:/root
步骤2:在目标主机上查看日志,找到要恢复数据的起始和结束偏移量
首先读取binlog日志,找到插入store4日志上面的at偏移量作为起始值,找到插入store5日志下面的COMMIT之后的at偏移量作为结束值;
[root@node10 ~]# ls /root/mybinlog/
mylog.000001 mylog.000002 mylog.index
[root@node10 ~]# mysqlbinlog /root/mybinlog/mylog.000002
[root@node10 ~]# mysqlbinlog --start-position=328 --stop-position=493 /root/mybinlog/mylog.000002 | mysql -uroot -pNSD2021@tedu.cn
验证:将只有在源服务器插入的数据恢复到目标服务器上(store4、store5)
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from nsd2021.departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 37 | store1 |
| 38 | store2 |
| 39 | store3 |
| 40 | store4 |
| 41 | store5 |
+---------+-----------+
37 rows in set (0.00 sec)
四、Percona概述
Percona 是一家专注于 MySQL 和 MariaDB 数据库技术的企业,提供了一系列高性能、高可用性和可扩展性的数据库解决方案。Percona 的产品和服务广泛应用于各种规模的企业,帮助它们优化数据库性能、提高数据可靠性并降低运营成本。
1、Percona XtraBackup:
是一个开源的 MySQL 备份工具,支持在线备份和增量备份。
- 支持热备份,无需锁定表。
- 提供增量备份和压缩功能。
- 支持多种存储引擎,包括 InnoDB 和 XtraDB。
- 适用于需要高可用性和数据保护的应用场景。
Percona解决的问题:
物理备份缺点:
- ① 跨平台性差
- ② 备份时间长、冗余备份、浪费存储空间
mysqldump备份缺点:
- ① 效率较低、备份和还原速度慢、锁表
- ② 备份过程中,数据插入和更新操作被阻塞
主要包含两个组件:
- ① xtrabackup:C程序,支持InnoDB/XtraDB
- ② innobackupex:以Perl脚本封装xtrabackup,还支持MyISAM引擎
2、安装Percona环境
可参考/lnmp_sort/4/.rpm: xtrabackup、libev依赖
步骤1:在yum服务器上生成yum源
[root@localhost ~]# cp percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm libev-4.15-1.el6.rf.x86_64.rpm /var/www/html/mysql
[root@localhost ~]# cd /var/www/html/mysql
[root@localhost mysql]# ls
percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm
libev-4.15-1.el6.rf.x86_64.rpm repodata
[root@localhost mysql]# createrepo -v . //-v输出详细信息
步骤2:在数据库服务器上安装percona
[root@localhost mysql]# yum -y install percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm
[root@localhost mysql]# rpm -ql precona-xtrabackup-24
/usr/bin/innobackupex //备份innodb、xtrdb、myisam引擎的表
/usr/bin/xbcloud
/usr/bin/xbcloud_osenv50
/usr/bin/xbcrypt
/usr/bin/xbstream
/usr/bin/xtrabackup //备份innodb、xtrdb引擎的表
查看命令帮助
# innobackupex --help //常用选项
# man innobackupex //详细帮助
3、Percona完全备份数据库
语法格式:
- ① 备份语法
innobackupex -u用户名 -p密码 备份目录名 [--no-timestamp]
注意:备份目录名不用提前创建
- ② 恢复语法
innobackupex --apply-log 备份目录名 //准备恢复数据
innobackupex --copy-back 备份目录名 //复制数据
补充:通过cat 备份目录名/xtrabackup_checkpoints,可查看备份目录状态
选项说明:
常用选项 | 含义 |
-u | 用户名 |
-p | 密码 |
--no-timestamp | 不带时间戳命名文件存储的子目录名 |
--apply-log | 准备恢复数据 |
--copy-back | 复制数据 |
--databases | --databases="库名" //1个库 --databases="库1 库2" //多个库 --databases="库1.表" //1张表 |
--incremental /目录名 | 新数据存放目录 |
--incremental-basedir=/目录名 | 备份新数据参考目录 |
--incremental-dir=/目录名 | 合并数据存放目录 |
完全备份数据库示例:
步骤1:源服务器192.168.2.5操作,进行完全备份数据到/pbackup/目录
① 方法1:在备份目录下生成带时间戳的子目录(备份目录不用提前创建)
[root@localhost ~]# innobackupex -uroot -pNSD2021@tedu.cn /pbackup/fullbackup //默认带时间戳
210609 10:47:54 innobackupex: Starting the backup operation
…
[root@localhost ~]# ls /pbackup/fullbackup/ //带时间戳的子目录
2021-06-09_10-47-54
[root@localhost ~]# ls /pbackup/fullbackup/2021-06-09_10-47-54/ //备份/var/lib/mysql的所有数据
backup-my.cnf ibdata1 mysql performance_schema xtrabackup_checkpoints xtrabackup_logfile
ib_buffer_pool mydb nsd2021 sys xtrabackup_info
② 方法2:不生成带时间戳的子目录
[root@localhost ~]# innobackupex -uroot -pNSD2021@tedu.cn /pbackup/full20210609 --no-timestamp //不带时间戳
210609 10:50:17 innobackupex: Starting the backup operation
…
[root@localhost ~]# ls /pbackup/full20210609/ //备份/var/lib/mysql的所有数据
backup-my.cnf ibdata1 mysql performance_schema xtrabackup_checkpoints xtrabackup_logfile
ib_buffer_pool mydb nsd2021 sys xtrabackup_info
步骤2:目标服务器192.168.2.10恢复数据
① 通过YUM安装percona
[root@node10 ~]# yum -y install percona-xtrabackup-24.x86_64
② 将源服务器的完全备份目录拷贝到目标服务器
[root@localhost ~]# scp -r /pbackup/ root@192.168.2.10:/root
# 查看备份目录状态(非必须步骤)(../xtrabackup_checkpoints)
[root@node10 ~]# cat /root/pbackup/
full20210609/ fullbackup/
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = full-backuped //备份类型为:已完全备份
from_lsn = 0 //起始日志序列号
to_lsn = 3738996 //结束日志序列号
last_lsn = 3739005
compact = 0
recover_binlog_info = 0
③ 准备恢复数据【--apply-log】
[root@node10 ~]# innobackupex --apply-log /root/pbackup/full20210609/
# 查看备份目录状态(非必须步骤)
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = full-prepared //备份类型为:已准备就绪
from_lsn = 0
to_lsn = 3738996
last_lsn = 3739005
compact = 0
recover_binlog_info = 0
④ 停止mysqld服务
[root@node10 ~]# systemctl stop mysqld
⑤ 恢复时要求mysql数据库目录为空
[root@node10 ~]# rm -rf /var/lib/mysql/*
⑥ 恢复数据(拷贝备份目录的数据,即/var/lib/mysql下数据)【--copy-back】
[root@node10 ~]# innobackupex --copy-back /root/pbackup/full20210609/
⑦ 修改mysql数据库目录的属主、属组权限
[root@node10 ~]# ls -ll /var/lib/mysql
总用量 122916
-rw-r-----. 1 root root 533 6月 9 12:36 ib_buffer_pool
-rw-r-----. 1 root root 12582912 6月 9 12:36 ibdata1
-rw-r-----. 1 root root 50331648 6月 9 12:36 ib_logfile0
-rw-r-----. 1 root root 50331648 6月 9 12:36 ib_logfile1
-rw-r-----. 1 root root 12582912 6月 9 12:36 ibtmp1
drwxr-x---. 2 root root 66 6月 9 12:36 mydb
drwxr-x---. 2 root root 4096 6月 9 12:36 mysql
drwxr-x---. 2 root root 188 6月 9 12:36 nsd2021
drwxr-x---. 2 root root 8192 6月 9 12:36 performance_schema
drwxr-x---. 2 root root 8192 6月 9 12:36 sys
-rw-r-----. 1 root root 443 6月 9 12:36 xtrabackup_info
[root@node10 ~]# chown -R mysql:mysql /var/lib/mysql
[root@node10 ~]# ls -ll /var/lib/mysql
总用量 122916
-rw-r-----. 1 mysql mysql 533 6月 9 12:36 ib_buffer_pool
-rw-r-----. 1 mysql mysql 12582912 6月 9 12:36 ibdata1
-rw-r-----. 1 mysql mysql 50331648 6月 9 12:36 ib_logfile0
-rw-r-----. 1 mysql mysql 50331648 6月 9 12:36 ib_logfile1
-rw-r-----. 1 mysql mysql 12582912 6月 9 12:36 ibtmp1
drwxr-x---. 2 mysql mysql 66 6月 9 12:36 mydb
drwxr-x---. 2 mysql mysql 4096 6月 9 12:36 mysql
drwxr-x---. 2 mysql mysql 188 6月 9 12:36 nsd2021
drwxr-x---. 2 mysql mysql 8192 6月 9 12:36 performance_schema
drwxr-x---. 2 mysql mysql 8192 6月 9 12:36 sys
-rw-r-----. 1 mysql mysql 443 6月 9 12:36 xtrabackup_info
⑧ 启动Mysql服务
[root@node10 ~]# systemctl start mysqld
4、Percona完全备份恢复单张表
表空间:
- 数据驻留在磁盘上的位置,称为数据目录,如/var/lib/mysql
- 从MySQL 5.6.6版开始,用户可以创建并指定他们想要存储数据的表空间,从而实现数据操作和恢复过程的吞吐量。
- InnoDB的表文件功能为每个表提供了单独的.ibd数据和索引文件,代表一个单独的通用表空间。这样数据库中的每个表都可以指向数据目录的不同位置。
补充:frm表结构、ibd表空间
- MySQL中.frm文件:保存了每个表的元数据,包括表结构的定义等,该文件与数据库引擎无关。
- MySQL中.ibd文件:InnoDB引擎开启了独立表空间(my.ini中配置innodb_file_per_table = 1)产生的存放该表的数据和索引的文件
— 恢复单表步骤:
① 删除待恢复表的表空间 (表名.ibd)
② 导出备份目录中的表信息(表名.cfg、表名.exp)
③ 拷贝表信息文件到数据库目录下(表名.cfg、表名.exp、表名.ibd)
④ 修改表信息文件的所有者及组用户为mysql
⑤ 导入拷贝的表空间
⑥ 删除数据库目录下的表信息文件
⑦ 验证:查看表记录
- 格式:alter table 表名 discard tablespace; //通过MySQLl删除表空间
- 格式:alter table 表名 import tablespace; //通过MySQL导入表空间
完全备份恢复单张表示例:
① 假设误操作删除表内容
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> truncate nsd2021.salary; //清空表记录
mysql> select * from salary;
Empty set (0.00 sec)
② 恢复准备:删除待恢复表的表空间 (salary.ibd)
[root@node10 ~]# ls /var/lib/mysql/nsd2021/ //删除表空间前,salary.ibd存在
db.opt departments.frm departments.ibd employees.frm employees.ibd
salary.frm salary.ibd wage_grade.frm wage_grade.ibd
mysql> alter table salary discard tablespace; //通过mysql删除表空间
Query OK, 0 rows affected (0.00 sec)
[root@node10 ~]# ls /var/lib/mysql/nsd2021/ //删除表空间后,salary.ibd消失
db.opt departments.frm departments.ibd employees.frm employees.ibd
salary.frm wage_grade.frm wage_grade.ibd
③ 在备份目录中,导出表信息(包括.exp和.cfg)【--apply-log --export】
[root@node10 ~]# innobackupex --apply-log --export /root/pbackup/fullbackup/2021-06-09_10-47-54/
[root@node10 ~]# ls /root/pbackup/fullbackup/2021-06-09_10-47-54/nsd2021/
db.opt departments.frm employees.exp salary.cfg salary.ibd wage_grade.frm
departments.cfg departments.ibd employees.frm salary.exp wage_grade.cfg wage_grade.ibd
departments.exp employees.cfg employees.ibd salary.frm wage_grade.exp
④ 拷贝表信息文件到数据库目录下(salary.{cfg,exp,ibd})
[root@node10 ~]# cp /root/pbackup/fullbackup/2021-06-09_10-47-54/nsd2021/salary.{cfg,exp,ibd} /var/lib/mysql/nsd2021/
⑤ 修改表信息文件的所有者及组用户为mysql
[root@node10 ~]# chown mysql:mysql /var/lib/mysql/nsd2021/salary.*
[root@node10 ~]# ls -ll /var/lib/mysql/nsd2021/
总用量 968
-rw-r-----. 1 mysql mysql 67 6月 9 12:36 db.opt
-rw-r-----. 1 mysql mysql 8606 6月 9 12:36 departments.frm
-rw-r-----. 1 mysql mysql 98304 6月 9 12:36 departments.ibd
-rw-r-----. 1 mysql mysql 8800 6月 9 12:36 employees.frm
-rw-r-----. 1 mysql mysql 131072 6月 9 12:36 employees.ibd
-rw-r--r--. 1 mysql mysql 671 6月 9 14:35 salary.cfg
-rw-r-----. 1 mysql mysql 16384 6月 9 14:35 salary.exp
-rw-r-----. 1 mysql mysql 8694 6月 9 12:36 salary.frm
-rw-r-----. 1 mysql mysql 589824 6月 9 14:35 salary.ibd
-rw-r-----. 1 mysql mysql 8646 6月 9 12:36 wage_grade.frm
-rw-r-----. 1 mysql mysql 98304 6月 9 12:36 wage_grade.ibd
⑥ 恢复数据:导入表空间
mysql> alter table salary import tablespace;
Query OK, 0 rows affected (0.01 sec)
⑦ 删除数据库目录下的表信息文件
[root@node10 ~]# rm -f /var/lib/mysql/nsd2021/salary.{cfg,exp}
⑧ 验证:查看表记录
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select count(*) from nsd2021.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)
5、Percona增量备份
增量备份基础:备份自上次备份以来的数据,一般来说需要有一个完全备份
- 语法格式:
① 备份语法:innobackupex -u 用户名 -p 密码 [ --databases=”数据库名.列表” ] --incremental 增量备份目录 --incremental-basedir=备份目录名 [ --no-timestamp ]
注意:第一次增量备份以完全备份为基础,第二次增量备份以第一次增量备份为基础,以此类推
② 恢复语法:
# 准备恢复数据
innobackupex --apply-log --redo-only 首次备份目录名
# 合并数据
innobackupex --apply-log --redo-only 首次备份目录名 --incremental-dir=合并增量备份目录名
# 恢复数据
innobackupex --copy-back 首次备份目录名
注意:第一次增量恢复以【首次完全备份】为基础并进行与【增量备份】合并,再将合并后的【完全备份】进行恢复;第二次增量备份以【增量备份合并完全备份】为基础并再进行与【增量备份】合并,再次对合并后的【完全备份】进行恢复;
增量备份示例1:
步骤1:在源服务器上添加数据
[root@localhost ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> insert into nsd2021.departments(dept_name) values('market1'),('market2'),('market3');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 31 | market1 |
| 32 | market2 |
| 33 | market3 |
+---------+-----------+
29 rows in set (0.00 sec)
步骤2:在源服务器上进行增量备份
[root@localhost ~]# innobackupex -uroot -pNSD2021@tedu.cn --incremental /pbackup/incr20210609 --incremental-basedir=/pbackup/full20210609/ --no-timestamp
[root@localhost ~]# cat /pbackup/full20210609/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0 //起始时间序列号
to_lsn = 3738996 //结束时间序列号
last_lsn = 3739005
compact = 0
recover_binlog_info = 0
[root@localhost ~]# cat /pbackup/incr20210609/xtrabackup_checkpoints
backup_type = incremental //备份类型为增量
from_lsn = 3738996 //起始时间序号(是完全备份目录的结束时间序列号作为起始)
to_lsn = 3739306 //结束时间序号
last_lsn = 3739315
compact = 0
recover_binlog_info = 0
步骤3:在目标服务上进行恢复数据
① 在目标服务器上删除原有日志
[root@node10 ~]# rm -rf /root/pbackup/
② 将日志拷贝到目标服务器
[root@localhost ~]# scp -r /pbackup/ root@192.168.2.10:/root/
[root@node10 ~]# ls /root/pbackup/
full20210609 fullbackup incr20210609
③ 准备恢复数据(完全备份目录)【--apply-log --redo-only 】
[root@node10 ~]# innobackupex --apply-log --redo-only /root/pbackup/full20210609/
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = log-applied
from_lsn = 0
to_lsn = 3738996
last_lsn = 3739005
compact = 0
recover_binlog_info = 0
④ 合并日志(完全备份目录+增量备份目录)【--apply-log --redo-only --incremental-dir=】
[root@node10 ~]# innobackupex --apply-log --redo-only /root/pbackup/full20210609/ --incremental-dir=/root/pbackup/incr20210609/
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = log-applied
from_lsn = 0
to_lsn = 3739306 //结束时间序号(是增量备份目录的结束时间序列号)
last_lsn = 3739315
compact = 0
recover_binlog_info = 0
⑤ 停止目标服务器mysqld服务
[root@node10 ~]# systemctl stop mysqld
⑥ 清空数据库目录下的所有文件
[root@node10 ~]# rm -rf /var/lib/mysql/*
⑦ 恢复数据【--copy-back】
[root@node10 ~]# innobackupex --copy-back /root/pbackup/full20210609/
⑧ 修改属主属组
[root@node10 ~]# chown -R mysql:mysql /var/lib/mysql
⑨ 启动目标服务器mysqld服务
[root@node10 ~]# systemctl start mysqld
验证,查看增量部分的数据
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use nsd2021;
mysql> select * from departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 31 | market1 |
| 32 | market2 |
| 33 | market3 |
+---------+-----------+
29 rows in set (0.00 sec)
增量备份示例2:重复增量备份
步骤1:源服务器再次增加数据
mysql> insert into departments(dept_name) values('sales1'),('sales2'),('sales3');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 34 | sales1 |
| 35 | sales2 |
| 36 | sales3 |
+---------+-----------+
32 rows in set (0.00 sec)
步骤2:源服务器增量备份
--incremental-basedir—> incr20210609,以上一次备份为基础
[root@localhost ~]# innobackupex -uroot -pNSD2021@tedu.cn --incremental /pbackup/incr20210609-2 --incremental-basedir=/pbackup/incr20210609/ --no-timestamp
# 将日志拷贝到目标服务器
[root@localhost ~]# scp -r /pbackup/incr20210609-2/ root@192.168.2.10:/root/pbackup/
步骤3:在目标服务上进行恢复数据
[root@node10 ~]# ls /root/pbackup/
full20210609 fullbackup incr20210609 incr20210609-2
① 准备恢复数据(上一次合并后的完全备份目录)【--apply-log --redo-only 】
[root@node10 ~]# innobackupex --apply-log --redo-only /root/pbackup/full20210609/
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = log-applied
from_lsn = 0
to_lsn = 3739306 //结束时间序号(是第一次合并增量备份目录后的结束时间序列号)
last_lsn = 3739315
compact = 0
recover_binlog_info = 0
② 合并日志(【完全备份目录+增量备份目录】+增量备份目录)
[root@node10 ~]# innobackupex --apply-log --redo-only /root/pbackup/full20210609/ --incremental-dir=/root/pbackup/incr20210609-2/
[root@node10 ~]# cat /root/pbackup/full20210609/xtrabackup_checkpoints
backup_type = log-applied
from_lsn = 0
to_lsn = 3739597 //结束时间序号(是第二次合并增量备份目录后的结束时间序列号)
last_lsn = 3739606
compact = 0
recover_binlog_info = 0
③ 停止目标服务器mysqld服务
[root@node10 ~]# systemctl stop mysqld
④ 删除工作目录
[root@node10 ~]# rm -rf /var/lib/mysql/*
⑤ 恢复数据
[root@node10 ~]# innobackupex --copy-back /root/pbackup/full20210609/
⑥ 修改属主属组
[root@node10 ~]# chown -R mysql:mysql /var/lib/mysql
⑦ 启动目标服务器mysqld服务
[root@node10 ~]# systemctl start mysqld
验证,查看增量的数据
[root@node10 ~]# mysql -uroot -pNSD2021@tedu.cn
Mysql> use nsd2021;
mysql> select * from departments;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 34 | sales1 |
| 35 | sales2 |
| 36 | sales3 |
+---------+-----------+
32 rows in set (0.00 sec)
思维导图1:
思维导图2:
小结:
本篇章节为【第四阶段】RDBMS1-DAY6 的学习笔记,这篇笔记可以初步了解到 MySQL索引(索引分类、创建索引)、用户及授权(创建用户并授权、查看授权、撤销授权、授权库mysql)、root密码恢复、备份、使用mysqldump进行逻辑备份、Percona。
Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。