03 . MysSQL权限和备份

时间:2022-07-25
本文章向大家介绍03 . MysSQL权限和备份,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

MySQL权限介绍

mysql中存在4个控制权限的表,分别为

user
db
tables_priv
columns_priv

用户和权限内容放在mysql库中,该库中有一张名为user的表,记录了用户的信息

查看用户信息的方式

select * from mysql.userG;

用户列

包含host、user、password三个字段,分别表示主机,用户以及用户密码 登陆mysql时只有匹配用户列中的数据才能成功登陆mysql,host和user字段为该表中的联合主键,用于唯一的标识用户身份

权限列

权限列规定了用户的权限,描述了用户的权限范围,只有带有y的权限标识该用户拥有的权限,如果为n标识该用户没有该权限,权限列使用了enum枚举的数据类型,可选项为y或n 即为有权限和无权限两种选择

安全列

安全列有两个ssl相关内容用于加密,两个和x509相关内容标识用户 ,plugin标识验证码用户身份的插件,authentication5.7版本之后用户标记密码,而password字段在5.7版本中消失

Select_priv: Y      		    #  查询权限

Insert_priv: Y         			# 写入权限

Update_priv: Y       			#  更新权限

Delete_priv: Y         		    # 删除权限

Create_priv: Y       			# 创建权限

Drop_priv: Y      			    # 删除权限

Reload_priv: Y     		        # 重载权限(是否可以使用flush)

Shutdown_priv: Y      		    # 关闭mysql进程的权限

Process_priv: Y       			# 管理进程的权限

File_priv: Y        			# 文件权限

Grant_priv: N       			# 给其他人授权权限

References_priv: Y        		# 建立约束权限 

Index_priv: Y          		    # 管理索引权限

Alter_priv: Y          		    # 修改权限

Show_db_priv: Y       		    # 查看数据库权限

Super_priv: Y                   # 超级权限  change master,清空二进制文件,设置全局变量set global

Create_tmp_table_priv: Y        # 创建临时表权限

Lock_tables_priv: Y          	# 锁表权限

Execute_priv: Y         		# 执行函数和存储过程的权限

Repl_slave_priv: Y          	# 对于复制(slave)的特殊操作的权限 

Repl_client_priv: Y           	# 查看master和slave权限

Create_view_priv: Y             # 创建视图权限

Show_view_priv: Y         	    # 查看视图权限

Create_routine_priv: Y          # 创建函数或者存储过程权限

Alter_routine_priv: Y           # 修改函数或者存储过程的权限

Create_user_priv: Y          	# 创建用户权限

Event_priv: Y         			# 事件权限

Trigger_priv: Y         		# 管理触发器权限

Create_tablespace_priv: Y       # 创建表空间的权限

# 资源控制列

max_questions: 0				# 用户每小时允许执行查询操作的次数

max_updates: 0				    # 用户每小时允许执行更新操作的次数

max_connections: 0			    # 用户每小时允许执行连接操作的次数

max_user_connections: 0		    # 用户允许同时建立连接的次数

# 0标识不作限制,如果设定了资源控制列,用户只能在单位时间内做指定次数的操作,超过指定次数立马禁止执行该操作

select_princ.N			        # 查看权限

insert_princ.N			        # 写入权限

update_princ.N		            # 更新权限

delete_princ.N		            # 删除(数据)权限

create_princ.N		            # 创建权限
mysql权限表的验证过程

1 . 先从user表中的Host,User,Password这3个字段中判断连接的ip、用户名、密码是否存在,存在则通过验证。 2 . 通过身份认证后,进行权限分配,按照user,db,tables_priv,columns_priv的顺序进行验证。即先检查全局权限表user,如果user中对应的权限为Y,则此用户对所有数据库的权限都为Y,将不再检查db, tables_priv,columns_priv;如果为N,则到db表中检查此用户对应的具体数据库,并得到db中为Y的权限;如果db中为N,则检查tables_priv中此数据库对应的具体表,取得表中的权限Y,以此类推。

DCL(Data Control Language 数据库控制语言)

用于数据库授权、角色控制等操作

GRANT授权,为用户赋予访问权限

REVOKE 取消授权,撤回授权权限

用户管理

# 创建用户
    create user '用户名'@'IP地址' identified by '密码';

# 查看数据库中自带用户
# select user,host from mysql.user;        

# 创建用户并设置密码
create user alice@'%' identified by '123';   # 去掉后面,用户没密码
create user alice@'localhost' identified by '123';
create user jack@'172.16.140.2' identified by '123';
create user rose@'172.16.140.%' identified by '123';
select user,host,authentication_string from mysql.user;

# 删除用户
drop user aaa@%;       # 默认删除的是%的
drop user shrek@'localhost';     # 不是默认的需要指明
delete from mysql.user where user='shrek' and host='%';


# 删除用户
    drop user '用户名'@'IP地址';
    delete from mysql.user WHERE host=主机名 and user = 用户名;

# 修改用户
    rename user '用户名'@'IP地址' to '新用户名'@'IP地址' ;

# 修改密码
    # 第一种方法:
    set password for '用户名'@'IP地址'=Password('新密码')

    # 第二种方法:
    alter user '用户名'@'IP地址' identified by '新密码';

   # 第三种方法(忘记密码时,必须使用此方法修改密码):
    UPDATE mysql.user SET authentication_string='' WHERE user='root' and host='localhost';
  

  
# 用户权限相关数据保存在mysql数据库的user表中,所以也可以直接对其进行操作(不建议)

权限管理

关于权限

all privileges  除grant外的所有权限
select          仅查权限
select,insert   查和插入权限
...
usage                   无访问权限
alter                   使用alter table
alter routine           使用alter procedure和drop procedure
create                  使用create table
create routine          使用create procedure
create temporary tables 使用create temporary tables
create user             使用create user、drop user、rename user和revoke  all privileges
create view             使用create view
delete                  使用delete
drop                    使用drop table
execute                 使用call和存储过程
file                    使用select into outfile 和 load data infile
grant option            使用grant 和 revoke
index                   使用index
insert                  使用insert
lock tables             使用lock table
process                 使用show full processlist
show databases          使用show databases
show view               使用show view
update                  使用update
reload                  使用flush
shutdown                使用mysqladmin shutdown(关闭MySQL)
super                   使用change master、kill、logs、purge、master和set global。还允许mysqladmin调试登陆
replication client      服务器位置的访问
replication slave       由复制从属使用
grant  权限 on 数据库.表  to  '用户'@'IP地址' identified by '密码';   -- 授权并设置密码
revoke 权限 on 数据库.表 from '用户'@'IP地址'    -- 取消权限

# with_option参数
    GRANT OPTION:					#	给用户授权权限,允许用户将自己的权限再授权给其他用户
    MAX_QUERIES_PER_HOUR: 			#    定义每小时允许执行的查询数
    MAX_UPDATES_PER_HOUR:			# 定义每小时允许执行的更新数
    MAX_CONNECTIONS_PER_HOUR:	    # 定义每小时可以建立的连接数
    MAX_USER_CONNECTIONS:			# 定义单个用户同时可以建立的连接数
关于用户和 IP
用户名@IP地址         # 用户只能在此 IP 下才能访问
用户名@192.168.1.%   # 用户只能在此 IP 段下才能访问(通配符%表示任意)
用户名@%.shark.com
用户名@%             # 用户可以再任意IP下访问(默认IP地址为%)
Example1
# 两个终端测试授权效果

create user 'shark'@'%';
grant all privileges on *.*  to 'shark'@'%' identified by '123';

# 创建用户直接授权
grant select on *.*     /*设置查询数据的权限在所有的库和表*/
 to 'shark_2'@"%"       /*指定用户名和来源 ip*/
 identified by '123';   /*设置密码*/

/*将数据读取到内存中,从而立即生效。*/
flush privileges

# 新建用户没有任何权限
create user youmen@'localhost' identified by 'ZHOUjian.20';
show grants for youmen@'localhost';
+--------------------------------------------+
| Grants for youmen@localhost                |
+--------------------------------------------+
| GRANT USAGE ON *.* TO 'youmen'@'localhost' |
+--------------------------------------------+

mysql -uyoumen -pZHOUjian.20 -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+


# 授权已存在用户相应权限
# 创建用户并授予所有库所有表的权限
create user zhou@'localhost' identified by 'ZHOUjian.20';
grant select,create on *.* to zhou@'localhost';
show grants for zhou@'localhost';
+---------------------------------------------------+
| Grants for zhou@localhost                         |
+---------------------------------------------------+
| GRANT SELECT, CREATE ON *.* TO 'zhou'@'localhost' |
+---------------------------------------------------+


grant select,update,insert,delete,create,drop on *.* to zhou@'localhost';
show grants for zhou@'localhost';
+---------------------------------------------------------------------------------+
| Grants for zhou@localhost                                                       |
+---------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON *.* TO 'zhou'@'localhost' |
+---------------------------------------------------------------------------------+

grant all on *.* to zhou@'localhost';
show grants for zhou@'localhost';
+---------------------------------------------------+
| Grants for zhou@localhost                         |
+---------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'zhou'@'localhost' |
+---------------------------------------------------+
Example2
# 创建用户并授权某一个库的所有表相应权限
grant select on youmen.* to youmen@'localhost' identified by 'ZHOUjian.20';

# 创建用户授予某一个库的某一个表相应权限
grant select on youmen.tb1 to youmen@'localhost' identified by 'ZHOUjian.20';

# 创建用户并授予某一个库的某一个表某一个列相应权限
drop user jian@'localhost';
grant select(name) on company.t2 to jian@'localhost' identified by 'ZHOUjian.20';

查看授权信息

# mysql.user表中存储了所有用户的信息
select * from mysql.userG;

# mysql.db表中保存了用户对表的权限
select * from mysql.dbG;

# mysql.tables_priv表中保存了用户对表的权限
select * from mysql.tables_privG;

# mysql.columns_priv表中保存了用户对列的权限
select * from mysql.columns_privG;


# 查看授权语句
show grants for '用户'@'IP地址';  

# 查看生效的授权信息,针对所有库和表的权限,比如 .  去mysql.user中查看
select * from mysql.user where user='shark'G;

# 针对具体到库的权限,比如`db_name.* 去mysql.db中查看
select * from mysql.db  where user='shark'G;

# 针对具体表的授权,在mysql.tables_priv中查看
select * from mysql.tables_priv where user='shark'G

收回权限

权限收回意味着将赋予用户的权限进行全部收回或者部分收回,一旦收回,用户就不再拥有执行该操作的能力,且权限不能通过grant收回,必须通过revoke进行回收

语法

REVOKE 权限列表 ON 数据库名 FROM 用户名@‘客户端主机’

# 收回所有权限
revoke all privileges,grant option from 'user'@'host','user'@'host'...
revoke all privileges,grant option from 'youmen'@'localhost';

# 回收部分权限
revoke delete,create,drop on *.* from zhou@'localhost';
revoke priv,priv... on db.table from 'user'@'host'

# mysql的库中的user表显示为全局权限,意味着该用户只能在所有库所有表都拥有该权限,该权限字段才会显示为Y,否则为N

假如是 MySQL8.x

CREATE USER '你的用户名'@'localhost' IDENTIFIED BY '你的密码';
#创建新的用户
GRANT ALL PRIVILEGES ON 你的数据库名.* TO '你的用户名'@'localhost';
#把刚刚创建的数据库的管理权限给予刚刚创建的MySQL用户
FLUSH PRIVILEGES;
#刷新权限,使用设置生效

MySQL数据备份

为什么要备份?

灾难恢复,需求改变,审计,测试等: 如"测试" 定期使用最新的生产环境中的数据更新到测试环境服务器. 主要针对myisam和innodb两种存储引擎做备份.

备份前需要考虑

# 1. 需要备份的数据库、该库的大小、它使用哪种引擎
# 2. 选择什么备份工具以及使用哪种备份方式
# 3. 锁和宕dang机带来的影响(备份之前需要加锁,不要让别人进行写操作)
# 4. 备份保存的位置最好不要放在同一台主机上面
# 5. 数据变化的频率
# 6. 行业规范或公司规定使用什么方式来备份

备份频率(每周,每日,每小时?)

根据数据的重要性和数据变化的频率性决定使用何种备份方式以及备份频率.

备份的文件

备份目录数据文件、二进制文件、配置文件

备份类型
# 1.根据服务是否在线
       # 热备份又称为在线备份:  备份期间不需要服务停机,业务不受影响
       # 温备份:  备份期间仅允许读的请求,不允许写
       # 冷备份又称为离线备份: 备份期间需要关闭Mysql服务.

# 2.根据备份的方式
      # 1. 物理备份:直接复制数据库文件,适用于大型数据库环境,不受存储引擎的限制,速度快,但不能恢复到异构系统中 linux,windows
       cp,tar, xtrabackup,ibbackup,lvm,snapshot
       
   	  # 2. 逻辑备份: 备份的是建库,建表,插入等操作所执行的sql语句,适用于中小型数据库,速度相对较低,但可跨平台linux sql > windows
       mysqldump,select      
       
# 3. 根据备份的数据量
       完全备份
       增量备份:        binlog日志进行备份
       差异备份:        (基本上用不到)
备份方式
   # 备份工具简介
   1.使用Mysqldump备份工具实现完全备份,并结合二进制日志实现增量备份.
       特点: 逻辑备份工具,支持InnoDB热备份,MyISAM温备份:备份与恢复较慢
   
   2.使用LVM逻辑卷快照功能实现几乎热备份的完全备份,并结合二进制日志实现增量备份.
       特点: 几乎接近于热备份,物理备份,备份与恢复较快.

   3.使用Xtrabakcup备份工具实现完全备份与增量备份.
       特点: 物理备份工具,支持InnoDB热备份,MyISAM温备份,速度较快.

Mysqldump备份

# Mysqldump[逻辑]
# 使用mysqldump实现逻辑备份
#   备份的是SQL语句,当数据达到上百G时,备份所花费时间较长,效率就不如物理备份了

# 语法:
   mysqldump  -h 服务器  -u 用户名 -p 密码  数据库名 >>  备份文件.sql

mysqldump -uroot -pZHOUjian.20 --lock-all-tables --flush-logs --all-databases > all.sql


--master-data={1,2}
 #  1:以CHANGE MASTER TO 的方式记录位置,可用于恢复后直接启动从服务器
 #  2:以CHANGE MASTER TO 的方式记录位置,但默认被注释
-x,--lock-all-tables       # 执行备份时为--databases有表请求加锁
-F,--flush-logs            # 备份之前刷新日志

# 备份某一个库
[root@mysqlhost ~]# mysqldump --databases school >> /opt/school.sql        

mysql> drop database school;
# 恢复
[root@mysqlhost ~]# mysql -uroot -pZHOUjian.20 < /opt/school.sql           

# 备份多个库
[root@mysqlhost ~]# mysqldump -uroot -pZHOUjian.20 school aaa ccc > /opt/more.sql  

# master-data 获取备份数据的Binlog位置和Binlog文件名,用于通过备份恢复的实例之间建立复制关系时使用,该参数会默认开启。

# dump-slave 用于在slave上dump数据,建立新的slave。因为我们在使用mysqldump时会锁表,所以大多数情况下,我们的导出操作一般会在只读备库上做,为了获取主库的Relay_Master_Log_File和Exec_Master_Log_Pos,需要用到这个参数,不过这个参数只有在5.7以后的才会有

# no-data, -d 不导出任何数据,只导出数据库表结构



[root@mysqlhost ~]# mysqldump -uroot -pZHOUjian.22 school student1 > /opt/table.sql  # 备份一张表
[root@mysqlhost ~]# mysqldump -uroot -pZHOUjian.22 --master-data=2 --flush-logs  school student1 student2 student3 > /opt/table.sql    # 备份多张表


# 备份流程:
# 1、备份
# 2、停服务
# 3、模拟数据全部丢失
# 4、初始化(二进制的初始化就是启动服务,源码初始化之后还要启动服务)
# 5、启动服务(二进制此步骤忽略)
# 6、改密码
# 7、恢复数据
# 8、mysql> flush privileges
# 9、重新登陆mysql用的就是备份的时候的密码了

Mysql日志管理

# 错误日志:        记录Mysql服务器启动、关闭及运行错误等信息.
# 二进制日志:    又称binlog日志,以二进制文件的方式记录数据库中除select以外的操作
# 慢查询日志:    记录执行时间超过指定时间的操作
# 中继日志:        备库将主库的二进制日志复制到自己的中继日志中,从而在本地进行重放
慢查询日志
# 修改配置文件
vim /etc/my.cnf

# 指定慢查询的时间
long_query_time=5                                                    

# 是否开启慢查询日志
slow_query_log=on                                                    

# 指定慢查询日志的文件名称及路径
slow_query_log_file=/backup/slow_log_file               

# 查询当前mysql数据库是否开启了慢查询日志功能:
mysql> show VARIABLES like '%slow%';
+---------------------------+------------------------------------+
| Variable_name             | Value                              |
+---------------------------+------------------------------------+
| log_slow_admin_statements | OFF                                |
| log_slow_slave_statements | OFF                                |
| slow_launch_time          | 2                                  |
| slow_query_log            | OFF                                |
| slow_query_log_file       | /var/lib/mysql/mysql_host-slow.log |
+---------------------------+------------------------------------+
bin-log

binlog日志是把数据库的每一个变化都记在到一个专用的文件里,select语句不记录,这种文件叫日志文件,mysql默认只打开错误日志文件,因为过多的日志会影响系统处理性能. mysql记录日志的开销比较大的,所以最好将日志单独分离到一个磁盘上,不要和数据放到同一块磁盘上,二进制的binlog日志需要mysqlbinlog工具查看.

方法一: 在配置文件中申明

mkdir /backup/master -p
vim /etc/my.cnf
[mysqld]
server-id=1
log-bin=/backup/master/mysql_logbin    # binlog索引文件
log-bin-index=/backup/master/mysql_index # 日志名称(不写名字默认以当前主机名加后缀为名字的)

# max-binlog-size=放置binlog大小过大
systemctl restart mysqld

ls /var/lib/mysql/mysql-bin.*
/var/lib/mysql/mysql-bin.000001  /var/lib/mysql/mysql-bin.index

# mysql-bin.index中存放的是索引,记录日志的个数和当前使用的日志的名称
# mysql-bin.000001中存放的是日志,将来还能产生000002和000003等

mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name                   | Value                            |
+---------------------------------+----------------------------------+
| log_bin                         | ON                               |
| log_bin_basename                | /backup/master/mysql_logbin      |
| log_bin_index                   | /backup/master/mysql_index.index |
| log_bin_trust_function_creators | OFF                              |
| log_bin_use_v1_row_events       | OFF                              |
| sql_log_bin                     | ON                               |
+---------------------------------+----------------------------------+
6 rows in set (0.01 sec)

方法二: 使用sql语句临时开启binlog日志

SET SQL_LOG_BIN=0;
SET SQL_LOG_BIN=1;
binlog2sql

因为官方的binlog查看SQL很吃力,可以使用一些开源工具binlog2sql,可以查看原生SQL

git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
pip install -r requirements.txt

查看binlog日志

# 获取binlog文件列表
mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       177 |
| mysql-bin.000002 |       154 |
+------------------+-----------+

# 查看当前正在写入的binlog文件
mysql> show master status; 

#    建议使用pos的方式进行恢复数据,因为使用datetime的方式有可能在同一时间有一个误删除一个正常插入,这样无法直接恢复删除的数据.
# 按时间

[root@mysqlhost ~]# mysqlbinlog /var/lib/mysql/mysql-bin.000001 --start-datetime="2019-10-30 13:44:30"
[root@mysqlhost ~]# mysqlbinlog /var/lib/mysql/mysql-bin.000001 --start-datetime="2019-10-30 13:44:30" --stop-datetime="2019-10-30 13:44:50"

# 按字节数
[root@mysqlhost ~]# mysqlbinlog /var/lib/mysql/mysql-bin.000001 --start-position=260  --stop-position=930

生成新bin-log日志文件

# 方法一:  在mysql中执行刷新日志的命令
mysql> flush logs;

# 方法二: 在命令行执行刷新日志的命令(可用于编写计划任务)
[root@mysqlhost ~]# mysqladmin -uroot -pZHOUjian.20 flush-logs;

# 方法三: 重启服务

# 方法四: 自然滚动
#	二进制文件单个文件超过1G大小

Mysqldump+Binlog备份和恢复

当我们要将数据恢复到任意时间点时候?

恢复时间点之前首先将全量备份恢复之后,在此基础上回放增加的binlog直至指定的时间点

# 通过日志文件可以恢复数据
# 1. 物理删除 rm -rf 物理文件,不记录binlog
# 2. 逻辑删除 drop database db,不记录binlog


rm -rf mysql-bin.00000*
rm -rf mysql-bin.index 

vim /etc/my.cnf       # 将数据和日志分离出来
[mysqld]
innodb_file_per_table=1
log-bin=/backup/master
log-bin-index=/backup/master
server_id=105

systemctl restart mysqld
Example1

准备库准备表

create database youmen;
use youmen

create table zhou(id int,age int,name varchar(20));
insert into zhou values(2,18,'zhou');
insert into zhou values(2,18,'jian');
insert into zhou values(2,18,'flying');
insert into zhou values(2,18,'haba');
# 生成新mysql-bin日志
flush logs;

# 模拟一下Mysql全备
mysqldump -uroot -pZHOUjian.20 --lock-all-tables --all_databases > all.sql


insert into zhou values(5,20,'jianjian');
insert into zhou values(6,21,'wunai');
insert into zhou values(7,22,'cjfwm');
flush logs;
# 生成新mysql-bin日志


# 我们可以看到
ll 
-rw-r--r-- 1 root  root  802543 May 13 11:41 all.sql
-rw-r----- 1 mysql mysql   1649 May 13 11:41 mysql_bin.000001
-rw-r----- 1 mysql mysql    341 May 13 11:43 mysql_bin.000002
-rw-r----- 1 mysql mysql    976 May 13 11:44 mysql_bin.000003
-rw-r----- 1 mysql mysql     75 May 13 11:43 mysql-bin.index

我们删除里面的库

mysqldump -uroot -pZHOUjian.20 --all-databases > all.sql
mysql> select * from zhou;
+------+------+--------+
| id   | age  | name   |
+------+------+--------+
|    2 |   18 | zhou   |
|    2 |   18 | jian   |
|    2 |   18 | flying |
|    2 |   18 | haba   |
+------+------+--------+


# 查看二进制日志信息
# mysqlbinlog --base64-output=DECODE-ROWS -v -v /backup/master.000002 > test.txt
mysqlbinlog /data/mysql-bin.000001 |mysql -uroot -pZHOUjian.20
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| youmen             |
+--------------------+


# 查看第一个和第二个日志中没有误删除,可以全部恢复
mysqlbinlog mysql_bin.000003 |mysql -uroot -pZHOUjian.20

# 看第三个日志,将删除数据的部分跳过
mysqlbinlog master.000003 --stop-position=320 |mysql -u root
mysqlbinlog master.000003 --start-position=797 |mysql -u root

# 最后一个日志文件中误删除的部分跳过
mysqlbinlog master.000004 --stop-position=1661 |mysql -u root

mysql> select * from zhou;
+------+------+----------+
| id   | age  | name     |
+------+------+----------+
|    2 |   18 | zhou     |
|    2 |   18 | jian     |
|    2 |   18 | flying   |
|    2 |   18 | haba     |
|    5 |   20 | jianjian |
|    6 |   21 | wunai    |
|    7 |   22 | cjfwm    |
+------+------+----------+
Example2
create database youmen;
use youmen

create table zhou(id int,age int,name varchar(20));
insert into zhou values(2,18,'zhou');
insert into zhou values(2,18,'jian');
insert into zhou values(2,18,'flying');
insert into zhou values(2,18,'haba');
# 生成新mysql-bin日志
flush logs;

# 模拟一下Mysql全备
mysqldump -uroot -pZHOUjian.20 --lock-all-tables --all_databases > all.sql


insert into zhou values(5,20,'jianjian');
insert into zhou values(6,21,'wunai');
insert into zhou values(7,22,'cjfwm');
flush logs;
# 生成新mysql-bin日志


# 我们记一下binlog此时的position
mysql> show master statusG;
*************************** 1. row ***************************
             File: mysql_bin.000002
         Position: 785327

insert into zhou values(12,18,'zhou');
insert into zhou values(13,18,'zhou');
insert into zhou values(14,18,'zhou');
insert into zhou values(15,18,'zhou');

# 接下来我们模拟一个误操作,错误插入
insert into zhou values(15,18,'HABA','zhou');

mysql> select * from zhou;
+------+------+--------+
| id   | age  | name   |
+------+------+--------+
|    2 |   18 | zhou   |
|    2 |   18 | jian   |
|    2 |   18 | flying |
|    2 |   18 | haba   |
|   12 |   18 | zhou   |
|   13 |   18 | zhou   |
|   14 |   18 | zhou   |
|   15 |   18 | zhou   |
+------+------+--------+

mysql> delete from zhou where id > 2;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from zhou;
+------+------+--------+
| id   | age  | name   |
+------+------+--------+
|    2 |   18 | zhou   |
|    2 |   18 | jian   |
|    2 |   18 | flying |
|    2 |   18 | haba   |
+------+------+--------+

mysql> flush logs;
# 接下来我们需求是将数据恢复到有12,13,14,15的那一次数据
# mysqlbinlog --base64-output=DECODE-ROWS -v -v /backup/master.000002 > test.txt

# 我们看一下现在的pos位置然后跟上一次的位置,然后把他们之间给过滤出来
mysql> show master statusG;
*************************** 1. row ***************************
             File: mysql_bin.000003
         Position: 786673

mysqlbinlog --start-position=785327 --stop-position=786673 /backup/mysql_bin.000002  > ./test.sql

mysql> source test.sql
mysql> select * from zhou;
+------+------+--------+
| id   | age  | name   |
+------+------+--------+
|    2 |   18 | zhou   |
|    2 |   18 | jian   |
|    2 |   18 | flying |
|    2 |   18 | haba   |
|   12 |   18 | zhou   |
|   13 |   18 | zhou   |
|   14 |   18 | zhou   |
|   15 |   18 | zhou   |
+------+------+--------+

Xtrabackup

Xtrabackup简介

Xtrabackup是世界上唯一一款开源的能够对InnoDB和XtraDB存储引擎的数据库备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个很好的替代品。 Xtrabackup有两个主要的工具: xtrabackup,innobackupex (1)xtrabackup只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表; (2)innobackupex-1.5.1封装了xtrabackup,是一个脚本封装,所以能同时备份处理innodb和myisam,但在处理myisam时需要加上一个读锁.

Xtrabackup的优缺点
# 优点:
#    1.备份速度快且可靠因为是物理备份
#    2.支持增量备份,更为灵活
#    3.备份过程中不会打断正在执行的事务
#    4.能够基于压缩等功能节约磁盘空间和流量
#    5.自动实现备份校验
#    6.还原速度快
# 缺点:
#    1.只能对innodb表做增量备份,myisam表增量备份时只能用作全备.
#    2.innobackupex备份Myisam表之前要对全库加锁,不能进行写操作,
#    3.若备份是从库上进行会直接影响到主从同步,造成延迟,但对innodb表不会阻塞读写.
Xtrabackup的工作原理:

在InnoDB内部会维护一个redo日志文件,又称之为事务日志文件,事务日志会存储每一个InnoDB表数据记录的修改,当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤: 它将已经提交的事务日志应用(前滚)到数据文件中存储下来,并将修改过但没有提交的数据进行回滚操作(即撤销掉,不进行任何操作)

Xarabackup的安装
yum -y install libev-devel
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.9/binary/redhat/6/x86_64/Percona-XtraBackup-2.4.9-ra467167cdd4-el6-x86_64-bundle.tar

wget http://www.percona.com/redir/downloads/Percona-XtraDB-Cluster/5.5.37-25.10/RPM/rhel6/x86_64/Percona-XtraDB-Cluster-shared-55-5.5.37-25.10.756.el6.x86_64.rpm        # 安装依赖包

yum install  perl-DBD-MySQL
wget ftp://ftp.pbone.net/mirror/apt.sw.be/redhat/el6/en/x86_64/rpmforge/RPMS/libev-4.15-1.el6.rf.x86_64.rpm
rpm -ivh libev-4.15-1.el6.rf.x86_64.rpm 
rpm -ivh Percona-XtraDB-Cluster-shared-55-5.5.37-25.10.756.el6.x86_64.rpm
yum install libmysql* -y
yum -y install percona-xtrabackup-24-2.4.9-1.el6.x86_64.rpm

[root@mysqlfrom ~]# rpm -ql percona-xtrabackup-24 |grep bin
/usr/bin/innobackupex            # 支持myisam,innodb
/usr/bin/xbcloud
/usr/bin/xbcloud_osenv
/usr/bin/xbcrypt
/usr/bin/xbstream
/usr/bin/xtrabackup
Xtrabackup全备及恢复

将数据库恢复到一个干净的环境

# xtrabackup的增量备份只能应用于InnoDB或者XtraDB,对于Myisam表执行增量备份其实进行的就是完全备份,所以没有意义

准备需要备份的库和表

create database xtradb;
use xtradb
create table sam(id int,name char(10)) engine=myisam;
insert into sam values(1,'alice');
create table inno(id int,name char(10));
insert into inno values(1,'jack');

# 注意: mysql需要对备份目录有rwx的权限
[root@mysqlfrom ~]# mkdir /backup
[root@mysqlfrom ~]# chown mysql:mysql /backup/

mysql> create user 'xtra'@'localhost' identified by 'ZHOUjian.21';
mysql>  grant reload,lock tables,replication client on *.* to xtra@'localhost';

# reload和lock tables权限是为了执行flush tables with read lock的操作

# replication client权限是为了获取bin log日志的位置

# root账号默认具备相应权限

mysql> select * from mysql.userG;
Example1

完整备份

create database youmen;
use youmen;
create table tb1(id int,age int,name varchar(10));
insert into tb1 value(1,1,'xiaoming');
insert into tb1 value(1,1,'youmen');

innobackupex --user=root --password=ZHOUjian.20 --host=localhost /backup/

# innobackupex --defaults-file=/etc/my.cnf --user=root --password=ZHOUjian.20 --host=localhost --socket=/var/lib/mysql/mysql.sock /backup/

ls /backup/2020-05-13_18-03-53/
backup-my.cnf   mysql                   xtrabackup_checkpoints  youmen
ib_buffer_pool  performance_schema      xtrabackup_info         zhou
ibdata1         sys                     xtrabackup_logfile
jian            xtrabackup_binlog_info  xtradb

xtrabackup相关文件的作用

(1)xtrabackup_checkpoints       # 备份类型(如完全或者增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN,LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
(2)xtrabackup_binlog_info       # mysql 服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志时间的位置。
(3)xtrabackup_info              # xtrabackup工具在备份时记录的使用工具及数据库信息
(4)backup-my.cnf                # 备份命令用到的配置选项信息
(5)xtrabackup_logfile           # xtrabackup记录innodb事务日志的信息,二进制文件,不能直接看

接下来我们模拟误删库

mysql> drop database zhou;

还原

# 准备
innobackupex --apply-log /backup/2020-05-13_18-03-53/

# 注意看my.cnf的datadir指定目录下面有不有数据,最好删干净

# 还原
innobackupex --user=root --password=ZHOUjian.20 --copy-back /backup/2020-05-13_18-03-53/


# 因为备份还原是root用户执行的, mysql启动时目录不能有root权限文件,服务会启动失败
# 修改权限
cd /var/lib/mysql/data/
chown mysql:mysql * -R
Xtrabackup增量备份恢复

第一个全量备份

create database youmen;
use youmen;
create table tb1(id int,age int,name varchar(10));
insert into tb1 value(1,1,'xiaoming');
insert into tb1 value(1,1,'youmen');

innobackupex --user=root --password=ZHOUjian.20 --host=localhost /backup/

# innobackupex --defaults-file=/etc/my.cnf --user=root --password=ZHOUjian.20 --host=localhost --socket=/var/lib/mysql/mysql.sock /backup/

ls /backup/2020-06-02_00-22-54/
backup-my.cnf   ibdata1  mysql               sys                     xtrabackup_info     xtradb
ib_buffer_pool  inc_rec  performance_schema  xtrabackup_checkpoints  xtrabackup_logfile  youmen

第一个增量备份

# 对数据库进行修改
use youmen
create table test(id int);
insert into test values(1);
insert into test values(2);

innobackupex --user=root --password=ZHOUjian.20 --incremental /backup/ --incremental-basedir=/backup/2020-06-02_00-22-54/

# --increment-basedir指定的目录是上一次增量备份所在的目录

du -sh /backup/2020-06-02_00-24-22
3.7M	/backup/2020-06-02_00-24-22

第二个增量备份

create database db;
use db
create table t1(id int);
insert into t1 values(1),(2),(3);

# 此处的incremental-basedir是上一次增量备份的文件名字
innobackupex --user=root --password=ZHOUjian.20 --incremental /backup/  --incremental-basedir=/backup/2020-06-02_00-24-22

模拟误删库

# 此处目录未上一次增量备份所在的目录
ll -h /backup/
total 12K
drwxr-x--- 8 root root 4.0K Jun  2 00:07 2020-06-02_00-07-51
drwxr-x--- 8 root root 4.0K Jun  2 00:08 2020-06-02_00-08-35
drwxr-x--- 9 root root 4.0K Jun  2 00:09 2020-06-02_00-09-16


mysql> drop database youmen;
mysql> drop database db;

# 模拟宕机
systemctl stop mysqld
# 数据丢失
rm -rf /var/lib/mysql/data/*

恢复完全备份

增量备份的恢复需要有3个步骤

# 1 . 恢复完全备份

# 2 . 恢复增量备份到完全备份(开始恢复的增量备份要添加--redo-only参数,到最后一次增量备份要去掉--redo-only)

# 3 . 对整体的完全备份进行恢复,回滚未提交的数据


# 先恢复一个全备
innobackupex --apply-log --redo-only /backup/2020-06-02_00-22-54/



# 将增量1应用到完全备份
innobackupex --apply-log --redo-only /backup/2020-06-02_00-22-54/ --incremental-dir=/backup/2020-06-02_00-24-22/

# 将增量2应用到完全备份
innobackupex --apply-log --redo-only /backup/2020-06-02_00-22-54/ --incremental-dir=/backup/2020-06-02_00-32-04/


# 把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据
innobackupex --apply-log  /backup/2020-06-02_00-22-54/ 


# 把恢复完的备份复制到数据文件目录中,给权限,重启数据库
innobackupex --copy-back /backup/2020-06-02_00-22-54/

chown mysql:mysql /var/lib/mysql/data/* -R
systemctl restart mysqld


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db                 |
| inc_rec            |
| mysql              |
| performance_schema |
| sys                |
| xtradb             |
| youmen             |
+--------------------+

mysql> use db

mysql> show tables;
+--------------+
| Tables_in_db |
+--------------+
| t1           |
+--------------+


mysql> select * from tt1;

mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+