8.MySQL安全管理

思考:在实际开发中,通常会需要对外提供一些数据,供其他项目去访问。这个时候就会出现一个问题,数据库怎么保证数据安全呢?

引入:当项目体量非常大的时候,的确会需要对外提供一些数据查询操作,或者项目大的时候需要多个项目共享数据。那么这个时候就会涉及到账户的安全问题以及数据的安全问题。在MySQL中,提供了多种方式来保证数据的安全。

  • 数据备份与还原:数据出错后最后一道保障
  • 用户权限管理:按需提供权限
  • 外键:表内部数据安全保护
  • 视图:虚拟表保护内部数据
  • 事务安全:规范数据的连续操作

总结:在MySQL中提供了很多的方式来保障数据的安全,因为数据安全是软件最重要的考量因素。

一、数据备份与还原【掌握】

定义:数据备份与还原,是指在数据安全的时候,将数据进行额外的存储,以防止数据出问题;而到了数据出了问题的时候,可以利用保存的安全数据还原成原来的样子。

在MySQL中,提供了很多种方式来实现数据的备份与还原

  • 文件备份与还原
  • 整库数据备份与还原
  • 单表数据备份与还原博客剖析
  • 增量备份与还原百度百科

总结:数据库的备份还原应该根据实际项目的需求来选择合适的方式,但是一定是要用到的。


思考:如果一个项目访问量非常小,数据量也不大,应该采用什么方式备份还原呢?

引入:理论上来讲,每一种备份方式都适合小项目,不过针对小项目通常采用的备份方式就是最简单的方式,文件备份。

1. 文件备份与还原【了解】

定义:文件备份与还原,就是利用MySQL数据表的结构、索引和数据文件,直接保存备份。还原的时候也是直接使用文件覆盖即可,此备份还原方式最简单。

  1. 文件备份:将数据库表对应文件复制到安全位置即可,但是InnoDB和MyIsam存储引擎有区别
  • InnoDB:需要备份三种文件
    • .frm文件:表结构文件
    • .ibd文件:数据和索引内容
    • ibdata1:InnoDB存储引擎的全部数据和索引文件
  • MyIsam:需要备份三种文件
    • .frm文件:表结构文件
    • .MYI文件:索引文件
    • .MYD文件:数据文件
  1. 文件还原:直接将备份文件放到对应数据库文件夹下即可

注意:InnoDB的还原的话需要使用备份ibdata1文件覆盖mysql\data\ibdata1文件

总结

  1. MySQL文件备份最简单,操作也最方便
  2. 文件备份会占用大量磁盘:结构、索引和数据
  3. InnoDB存储引擎不适合使用文件备份,MyIsam存储引擎适合

思考:文件备份太过冗余,而且如果备份频次高点的话,磁盘受不了。有么有别的方式来实现备份呢?

引入:一般项目中最常用的就是整库备份,也称之为SQL备份,备份的内容是将表的结构和数据已SQL指令的形式备份。

2.整库备份与还原【掌握】

定义:整库备份与还原,是利用mysql提供的客户端mysqldump.exe将数据库中指定的表或者整个数据库以SQL指令形式保存到文件,还原的时候只要执行文件中对应的SQL指令即可。

  1. mysqldump.exe备份:mysqldump是一种客户端,因此也需要像mysql.exe一样先进行连接认证;只是mysqldump备份的指令是直接跟在认证之后的
mysqldump.exe -h主机地址 -P端口 -u用户名 -p密码 数据库名字 [表名列表] > SQL文件路径
  1. mysqldump可以实现多种备份方式
  • 单表备份:数据库名字 表名 > SQL文件路径
  • 多表备份:数据库名字 表名1 表名2 ...表名N > SQL文件路径
  • 整库备份:数据库名字 > SQL文件路径
mysqldump -uroot -proot my_database my_class > D:/a.sql             #单表
mysqldump -uroot -proot my_database my_class my_student > D:/as.sql  #多表
mysqldump -uroot -proot my_database > D:/asd.sql                    #整库
  1. 还原:还原就是用备份的SQL指令执行一次,从而可以覆盖掉当前数据库内对应的表和数据
  • mysql客户端还原,即登录时直接还原:mysql.exe -hPup 数据库名字 < SQL文件路径
  • 指令还原,即登录mysql后还原:source SQL文件路径
mysql -uroot -p my_database < D:/a.sql  #还原(回车后输入密码)
source D:/as.sql;                      #还原(登录mysql服务端后)

注意:SQL还原时必须指定数据库名字

总结

  1. SQL文件备份是利用mysqldump.exe客户端实现
  2. 客户端备份需要先连接认证服务器
  3. SQL备份可以是单表、多表或者整库
  4. SQL还原可以使用mysql登录时还原,也可以在登录后使用source指令
  5. SQL还原必须指定好数据库

二、外键约束【掌握】

定义:外键foreign key,只在一张表中有一个字段指向另外一张表的主键字段,并且通过外键关联会有一些约束效果

思考:我们在学习表关系的时候,在一对多或者多对多的时候,都会在一张表中增加一个字段来指向另外一张表的主键,但是此时其实指向没有任何实际含义,需要人为的去记住,这样有啥价值呢?

引入:如果只是需要人为的去记住对应的关系,没有任何数据库本身的控制的话,那样的存在没有价值。Mysql提供了一种外键机制来实现约束关系。

1. 外键【掌握】

定义:外键就是在设定了字段属于其他表的主键后,使用foreign key关键字让表字段与另外表的主键产生内在关联关系。

  1. 创建表时增加外键:在所有字段后使用constraint `外键名字` foreign key (外键字段) references 表名(主键字段)
create table my_foreign(
    id int primary key auto_increment,
    name varchar(10) not null,
    age tinyint unsigned not null,
    c_id int comment '指向my_class的主键',
    constraint `my_class_id` foreign key(c_id) references my_class(id)
)charset utf8;
  1. 外键要求:字段本身必须是一个普通索引,如果不是,外键会自动加上,因此对应的外键字段的key为mul
mysql> desc my_foreign;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | int(11)             | NO   | PRI | NULL    | auto_increment |
| name  | varchar(10)         | NO   |     | NULL    |                |
| age   | tinyint(3) unsigned | NO   |     | NULL    |                |
| c_id  | int(11)             | YES  | MUL | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
  1. 删除外键:如果一张表明确不需要使用对应的外键,可以使用修改表结构删除:alter table 表名 drop foreign key `外键名字`;
alter table my_foreign drop foreign key `my_class_id`;

注意:删除外键对应的表字段索引依然是存在的

  1. 追加外键:即在创建表后增加外键字段:alter table 表名 add constraint `外键名字` foreign key(外键字段) references 外键表(主键);
alter table my_foreign add constraint `my_class_id` foreign key(c_id) references my_class(id);

总结

  1. 外键可以在新建表时和创建表后增加foreign key
  2. 外键对应字段会自动创建成一个普通索引
  3. 外键删除后不会清除外键字段的普通索引关系

思考:外键就是为了增加个字段吗?没有任何效果?

引入:既然已经关联了另外一张表的主键,说明外键必然是有效果的。这种效果称之为外键约束,会在数据操作时产生相应效果。

2. 外键约束【掌握】

定义:外键约束,即外键的增加之后对应的父表(主键表)和子表(外键所在表)都有相应的约束关系

  1. 外键增加后默认字表插入的数据对应的外键字段必须在父表存在,否则会报错
insert into my_foreign values(null,'犬夜叉',200,5);          #外键值5在主表中存在:OK

insert into my_foreign values(null,'神无',3,100);           #外键值100在主表不存在,报错
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`my_database`.`my_foreign`, CONSTRAINT `my_class_id` FOREIGN KEY (`c_id`) REFERENCES `my_class` (`id`))
  1. 外键增加后默认父表主键如果在外键值有使用,那么不能更新主键值,也不能删除主键所在记录
update my_class set id = 11 where id = 5;               #5在外键中存在,不能更新
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`my_database`.`my_foreign`, CONSTRAINT `my_class_id` FOREIGN KEY (`c_id`) REFERENCES `my_class` (`id`))

delete from my_class where id = 5;                      #5在外键中存在,不能删除
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`my_database`.`my_foreign`, CONSTRAINT `my_class_id` FOREIGN KEY (`c_id`) REFERENCES `my_class` (`id`))
  1. 因此,外键的作用就明确了
  • 限定子表(外键所在表)不能插入主表中不存在外键值(不能更新)
  • 限定父表(主键被引用)不能删除或者更新子表有外键引用的主键信息
  1. 可以在创建外键的之后指定外键的约束效果:即控制父表的操作对子表的影响
  • 控制情况
    • on update:父表更新与子表有关联的主键时
    • on delete:父表删除与子表有关联的主键时
  • 控制效果
    • cascade:级联操作,即父表怎么样,子表相有对应关系的记录就怎么样
    • set null:置空操作,即父表变化,子表关联的记录对应的外键字段置空(注意:能够使用的前提是外键对应的字段允许为空)
    • restrict/no action:严格模式,即不允许父表操作
  • 通常的搭配规则如下
    • on update cascade:父表更新,子表级联更新
    • on delete set null:父表删除,子表对应外键字段置空
create table my_foreign2(
    id int primary key auto_increment,
    name varchar(10) not null,
    age tinyint unsigned not null,
    c_id int comment '外键字段',
    constraint `my_class_id2` foreign key(c_id) references my_class(id) on update cascade on delete set null
)charset utf8;
insert into my_foreign2 values(null,'七宝',2,7);

注意:表中外键名字是整个数据库唯一的,不能重复,因此可以在创建表的时候自己不指定,即直接使用foreign key及以后的内容

更新父表效果

mysql> update my_class set id = 8 where id = 7;
Query OK, 1 row affected (0.17 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from my_foreign2;
+----+------+-----+------+
| id | name | age | c_id |
+----+------+-----+------+
|  1 | 七宝 |   2 |    8 |
+----+------+-----+------+
1 row in set (0.00 sec)

删除父表效果

mysql> select * from my_foreign2;
+----+------+-----+------+
| id | name | age | c_id |
+----+------+-----+------+
|  1 | 七宝 |   2 |    8 |
+----+------+-----+------+
1 row in set (0.00 sec)

mysql> delete from my_class where id = 8;
Query OK, 1 row affected (0.08 sec)

mysql> select * from my_foreign2;
+----+------+-----+------+
| id | name | age | c_id |
+----+------+-----+------+
|  1 | 七宝 |   2 | NULL |
+----+------+-----+------+
1 row in set (0.00 sec)

总结

  1. 外键约束分为对父表的约束和对子表的约束,其中子表约束是固定的不能插入父表不存在的外键值
  2. 父表外键约束可以通过设定on update和on delete事件来控制,控制方式有cascade、set null和restrict三种
  3. 外键的强大约束作用可以保证数据的完整性和有效性
  4. 外键的强大约束有可能操作负面影响:数据维护变得困难,所以实际开发中要根据需求选择使用
  5. 外键只有InnoDB存储引擎支持,MyIsam不支持

三、事务安全【掌握】

思考:MySQL如果出现用户的一次操作,在数据库中要操作两张表:如用户下单,对应商品表的数量要先减少,然后再在订单表中增加一条记录。如果在操作的过程中,只完成了一半就出现理论问题,这种数据该怎么办?

引入:很多时候数据操作都会存在步骤性,就是多个步骤完成才是一个统一的操作。这个时候如果不是人为控制的话,就很难保证。MySQL提供了一种事务安全,可以自动管理这种需求。

1. 事务安全【掌握】

定义:事务安全transaction safe是指有些操作是需要多次对表进行写操作(增删改),但是需要最后等所有结果都成功了才提交,其中一步错了,整个操作就无效,从而保证数据的整体性。

  1. 默认的MySQL是关闭事务的,即用户一提交操作,系统就自动将数据写入到数据表
# 在一个客户端写入数据,然后去另外一个客户端查看
insert into my_foreign2 values(null,'蜘蛛',188,5);
  1. 如果想要开启事务可以使用两种方式
  • 自动开启:修改系统事务控制变量autocommit
  • 手动事务:使用事务命令来控制要执行的事务操作

自动事务

mysql> show variables like 'autocommit';            #查看系统事务控制,默认是自动提交的
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set, 1 warning (0.01 sec)

# 修改自动提交
mysql> set autocommit = off;
Query OK, 0 rows affected (0.35 sec)

# 此时所有的写操作就不会自动写入到数据表了
mysql> insert into my_foreign2 values(null,'自来也',50,2);
#需要使用指令commit
mysql> commit;
Query OK, 0 rows affected (0.10 sec)

注意:当前修改只是当前客户端当次连接有效,关闭退出就失效了。

  1. 手动事务:即通过指令来控制事务的开启和结束
  • 开启事务:start transaction;
  • 执行事务:各类SQL写操作
  • 关闭事务:
    • commit:操作成功全部提交
    • rollback:操作失败全部回退
# 开启事务
start transaction;

# 执行事务
insert into my_class values(null,'神童1班','4001');    #执行成功后执行第二天,此时其他客户端看不到
insert into my_foreign2 values(null,'阿童木',0,8);     #使用第一条的结果

# 结束事务:判断前面是否成功,如果有失败则回退
rollback;                                           #前面所有操作都失败

# 注意:如果前面新增数据的时候用到了自增长,而最后选择了rollback,那么对自增长的触发是不可逆的.
  1. 事务回退:指事务操作过程中,某个节点成功了,但是后续未必会成功,那么可以设置节点,以后返回到该位置
  • 设置节点:savepoint 名字;
  • 回退到节点:rollback to 节点名字;
# 开启事务
start transaction;

# 执行事务
insert into my_class values(null,'神童1班','4001');    #执行成功后执行第二天,此时其他客户端看不到

# 设置节点
savepoint sp1;

# 继续执行
insert into my_foreign2 values(null,'阿童木',0,6);     #使用第一条的结果

# 假设执行失败,回退到成功节点
rollback to sp1;                                    #第二天执行无效

# 继续执行
insert into my_foreign2 values(null,'阿童木',0,9);

# 提交事务
commit;     
  1. 事务特点:ACID
  • 原子性(Atomicity ):一个事务操作是一个整体,不可拆分
  • 一致性(Consistency):事务操作要么全成功,要么全失败
  • 隔离性(Isolation ):事务操作过程中,其他事务不可见
  • 持久性(Durability ):事务一旦提交,结果不可改变
  • InnoDB支持,MyIsam不支持
  1. 事务锁:一个事务在操作某个数据的时候,会形成锁,其他事务不可操作(写操作,可读)
  2. 事务安全原理
  • 默认事务关闭:SQL写操作一旦执行,DBMS就会写入到数据表(其他客户立即可见)
  • 开启事务:系统将当前事务的操作记录到事务日志,当前用户自己查看的是DBMS加工结果数据
  • 提交事务:事务成功提交会一次性同步到表,而如果失败提交就会全部清空当前事务记录

总结

  1. 事务安全是一种保障连续操作完整性的机制

  2. 事务安全可以是自动事务(默认关闭)和手动事务,一般使用手动事务

  3. 事务处理过程中可以设置回滚点,从而实现部分回退

  4. 事务处理有四个特点:ACID

  5. MySQL中InnoDB支持事务,MyIsam不支持


四、视图【掌握】

思考:有这么一种需求,需要将我们数据库的数据提交给其他系统访问(仅允许访问),对方想要看到所有的班级和学生信息,该如何实现?

引入:最简单的一种方式是给数据库服务器的账号给对方,对方自己去查看。但是此时对方可以看到数据库里面的所有该看的和不该看的数据,容易造成安全隐患。此时可以使用视图机制来实现

1. 视图【掌握】

定义:视图View,是一种虚拟表结构,由select查询语句的结果组成。

  1. 定义视图:create view 视图名字 as select查询语句;
create view student_class 
as 
select s.*,c.name class_name,c.room class_room
from my_student2 s left join my_class c on s.class_id = c.id;
  1. 视图创建后可以使用表查看的所有方式进行查看
show tables;
desc student_class;
show create table/view student_class;

注意:视图是一种虚拟表,会产生表结构文件,但是没有数据和索引文件

8.MySQL安全管理_第1张图片
视图结构文件.png
  1. 修改视图:即修改视图的创建语句,修改有两种方式
  • 修改结构:alter view修改
  • 创建替换:create or replace view
alter view 视图名字 as 新select语句

# 创建替换
create or replace view student_view as select * from my_student2; #没有就新增,有就替换
  1. 删除视图:drop view 视图名字;
  2. 视图使用:视图有select语句组成结果,是提供数据的,可以像查询表一样查询数据
select * from student_class;

总结

  1. 视图可以通过create [or replace] view 视图名字 as select语句组成;
  2. 视图可以像表一样管理(查看)
  3. 视图主要目的是为了提供数据(通常是多表连接数据)

思考:视图是像表一样管理,那么视图可以进行数据的写操作吗?

引入:视图天生是为了数据查看的,一般不建议对视图进行数据操作,但是如果非要操作,视图也是允许的。

2. 视图数据操作【了解】

定义:视图数据操作,即通过视图进行增删改操作,视图本身不存储数据,数据来源于基表,所以视图操作是直接针对基表进行操作。

  1. 对视图进行新增数据操作,利用insert插入指令:视图分为单基表视图和多基表视图,多基表视图不能新增数据。
# 多基表视图
insert into student_class values(null,'阿童木','男',0,7,'神童1班','4001'); #错误

# 单表视图
insert into student_view values(null,'阿童木','男',0,7);    #单表视图可以插入数据
Query OK, 1 row affected (0.08 sec)

注意:单表视图插入数据的前提,是视图所包含的字段有基表中全部不能为空且没有默认值的字段,如果基表中有必填字段没有出现在视图了,就会报错失败!

  1. 更新数据,利用update更新指令:同样,多基表视图不能更新,单基表视图可以
# 多基表视图
update student_class set age = 30 where id = 1;             #错误,不可更新

# 单基表视图
update student_view set age = 30 where id = 1;              #可以
  1. 删除数据,利用delete删除指令:多基表视图不能删除,单基表视图可以
# 多基表视图
delete from student_class where id = 10;                    #错误,不可删除

# 单基表视图
delete from student_view where id = 10;                     #可以

总结

  1. 视图数据写操作要看视图的基表数量:多基表视图不可增删改,单基表视图可以
  2. 实际开发中,一般不会允许对视图进行数据写操作,只是用来提供数据查询

思考:视图本身是可以理解为一条select语句,那么查询视图的时候又是一条select语句,本质不就是一条子查询吗?

引入:视图查询的本质的确可以理解为就是一条子查询操作,而且是表子查询跟在from之后。但是视图还有深一层的内容,就是视图算法,能够与子查询有一些不一样。

3. 视图算法【了解】

定义:视图算法,就是在视图创建的时候采用指定的算法,系统在进行视图调用时会根据算法来优化视图的运算逻辑,从而也能达到不同的效果。

  1. 视图算法定义:create ALGORITHM = 算法 view 视图名字 as select查询语句;,MySQL中提供了三种视图算法
  • undefined:默认的,未定义算法,即系统自动选择算法
  • merge:合并算法,就是将视图外部查询语句跟视图内部select语句合并后执行,效率高(系统优先选择)
  • temptable:临时表算法,即系统将视图的select语句查出来先得出一张临时表,然后外部再查询(temptable算法视图不允许写操作)
# 创建三个视图,指定三种不同算法,内容一样
create ALGORITHM = undefined view student_v1 as select * from my_student2 order by age desc;
create ALGORITHM = merge view student_v2 as select * from my_student2 order by age desc;
create ALGORITHM = temptable view student_v3 as select * from my_student2 order by age desc;
  1. 组织查询:对视图数据进行分组统计
select count(*),class_id,max(age),any_value(name) from student_v1 group by class_id;
select count(*),class_id,max(age),any_value(name) from student_v2 group by class_id;
select count(*),class_id,max(age),any_value(name) from student_v3 group by class_id;
  1. 三组结果说明:算法不同,MySQL内部执行的方式不一样,如果要用到排序和分组,那么要考虑算法带来的影响

总结

  1. MySQL中视图有三种算法,在定义的时候确定,默认是undefined让系统自己选
  2. 视图算法主要是MySQL内部执行时的方式,系统喜欢选择merge(执行效率高)

五、用户权限管理【了解】

思考:MySQL安装的时候,给客户端预留了一个账号root,一个数据库中有很多项目,如果都用一个账号,岂不是没有数据安全可言?

引入:如果数据库只有一个账号,那肯定该账号不是公共账号,否则太危险。凡是较大项目中,都会根据不同人的权限,来分配不同的账号,以保障数据安全。

1. 用户管理【了解】

定义:用户管理,即在数据库中利用当前用户的权限去管理用户以及用户权限。

  1. root用户是超级管理员账户,拥有所有权限,也最不安全:用户在mysql中都包含两个部分,即用户名和主机地址(host):可以通过show grants for root@localhost; 来查看root用户权限
mysql> show grants for root@localhost;
+---------------------------------------------------------------------+
| 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.35 sec)

所有权限都在mysql数据库下的user表中

# root用户全是Y
mysql> select * from mysql.user\G
*************************** 1. row ***************************
                  Host: localhost
                  User: root
           Select_priv: Y
           Insert_priv: Y
           Update_priv: Y
           Delete_priv: Y
           Create_priv: Y
             Drop_priv: Y
           Reload_priv: Y
         Shutdown_priv: Y
          Process_priv: Y
             File_priv: Y
            Grant_priv: Y
       References_priv: Y
            Index_priv: Y
            Alter_priv: Y
          Show_db_priv: Y
            Super_priv: Y
 Create_tmp_table_priv: Y
  1. 一般我们项目中都不大会直接都使用root用户访问操作数据库(生产环境),这个时候会创建不同的账号给不同的团队,创建账号语法:create user 用户名@主机地址 identified by password '明文密码';
create user 'user1'@'%' identified by '123456'; #创建一个允许所有人访问的user1账户,密码123456
create user 'user2'@'localhost' identified by '123456'; #仅允许本机访问
  1. 赋予权限:默认的用户没有任何权限
C:\Users\DELL>mysql -uuser1 -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

赋予权限的语法:grant 权限列表 on 数据库.表名 to user

# 给user1 my_database中视图查看权限
grant select on my_database.student_view to 'user1'@'%';

# 给user2 全部权限
grant all privileges on *.* to 'user2'@'localhost';

  1. 取消权限:revoke 权限列表 on 数据库.表名 from user;
# 收回user1的查看权限
revoke select on my_database.student_view from 'user1'@'%';
  1. 如果用户密码忘了,可以帮助修改用户密码:set password for '用户名'@'主机地址'="新密码";
set password for 'user1'@'%'='654321';
  1. 回收账户即删除账户:drop user 用户名;
drop user 'user1'@'%';

总结

  1. root用户是超级管理员,拥有全部权限
  2. 项目实施中需要给不同的小组创建不同的账户,分配不同的权限
  3. 账号的权限要及时跟进,不用的权限要迅速回收,不用的账户要尽快删除

你可能感兴趣的:(8.MySQL安全管理)