MySQL之数据库安全性管理

本篇总结数据库相关安全性的知识点,包含外键约束、事务管理、预处理、视图、数据备份还原和用户管理 ~

首先,安全管理就是用各种方式来确保数据库的安全和数据的安全。我们经常见到表情包,某公司程序员删库跑路…
那么如果有用户管理,就可以通过权限限制其没有权限删除;如果有数据备份,即便数据删除,也可以很快的实现数据还原,减小损失。
然而,数据库安全的维度有很多,比如:管理安全~用户、权限、备份还原等; 结构安全~外键、视图、事务等; 执行层~预处理。

一、外键约束

1、外键

外键:foreign key,表中指向外部表主键的字段定义成外键

  • 语法 [constraint 外键名] foreign key(当前表字段名) references 外部表(主键字段)

  • 外键构成条件:

    • 外键字段必须与对应表的主键字段类型一致
    • 外键字段本身要求是一个索引(创建外键会自动生成一个索引)
  • 外键可以不指定名字,系统会自动生成

  • 一张表可以有多个外键,但是一个字段只能产生一个外键

例:创建专业表和学生表,学生表中的专业id指向专业表id

create table t_47(
	id int primary key auto_increment,
    name varchar(50) not null unique
)charset utf8;

create table t_48(
	id int primary key auto_increment,
    name varchar(50) not null,
    c_id int comment '指向t_46表中的id主键',
    constraint `c_id` foreign key(c_id) references t_47(id)
)charset utf8;

2、外键约束

外键约束:当表建立外键关系后,外键就会对主表(外键指向的表)和子表(外键所在的表)里的数据产生约束效果

  • 外键约束的是写操作(默认)
    • 新增:子表插入的数据对应的外键必须在主表存在
    • 修改:主表的记录如果在子表存在,那么主表的主键不能修改(主键不能修改)
    • 删除:主表的记录如果在子表存在,那么主表的主键不能删除
  • 外键约束控制:外键可以在定义时控制外键的约束作用
    • 控制类型
      • on update:父表更新时子表的表现
      • on delete:父表删除时子表的表现
    • 控制方式
      • cascade:级联操作,父表操作后子表跟随操作
      • set null:置空操作,父表操作后,子表关联的外键字段置空
      • restrict:严格模式,不允许父表操作(默认的)
      • no action:子表不管
  • 限制外键约束,一般使用更新级联,删除置空
    • on update cascade:更新级联
    • on delete set null:删除置空
  • 外键约束增强了数据的安全性和可靠性,但是会增加程序对于数据的不可控性,实际开发中外键使用较少

3、外键管理

外键管理:在表创建后期维护外键

  • 新增外键
alter table 表名 add [constraint `外建名`] foreign key(外键字段) references 表名(主键) [on 外键约束]
  • 删除外键
alter table 表名 drop foreign key 外键名;
  • 更新外键:先删除后新增

二、事务安全

1、事务

事务:要做的某个事情

  • 计算机中的事务是指某个程序执行单元(写操作)

  • 事务安全:当事务执行后,保障事务的执行是有效的,而不会导致数据错乱

  • 事务安全通常针对的是一连串操作(多个事务)而产生的统一结果

  • MySQL中默认的写操作是直接写入的

    • 执行写操作SQL,同步到数据表

例如银行转账:从A账户转账到B账户

(1)创建数据表

create table t_52(
	id int primary key auto_increment,
    name varchar(50) not null,
    account decimal(10,2) default 0.00
)charset utf8;

insert into t_52 values(null,'Tom',10000),(null,'Lucy',100);

(2)转账:Tom向Lucy转账,一定是分为两步

# Tom扣钱
update t_52 set account = account - 1000 where id = 1;

# Lucy收钱
update t_52 set account = account + 1000 where id = 2;
  • 以上两步必须都成功转账才能叫成功
  • 两步操作无法确保哪一步会出问题(尤其是第二步)
  • 保障两步都成功才能叫事务安全

事务安全原理

  • 事务安全是在操作前告知系统,接下来所有的操作都暂不同步到数据表,而是记录到事务日志,指导后续所有操作都成功,再进行同步;否则取消所有操作!!
  • 事务的目的就是为了保障连续操作的一致性,保证结果的完整性!!

2、事务处理

事务处理:利用自动或者手动方式实现事务管理

  • 自动事务处理:系统默认,操作结束直接同步到数据表(事务关闭状态)

    • 系统控制:变量 autocommit(值为ON,自动提交)
  • 手动事务处理

    • 开启事务: start transaction
    • 关闭事务
      • 提交事务:commit(同步到数据表同时清空日志数据)
      • 回滚事务:rollback(清空日志数据)
  • 事务回滚:在长事务执行中,可以在某个已经成功的节点处设置回滚点,后续回滚的话可以回到某个成功点

    • 设置回滚点:savepoint 回滚点名字
    • 回滚到回滚点:rollback to 回滚点名字
  • 事务处理要应用到多次写操作组成的大事务中,如金融安全等

  • 事务处理通常都会使用手动控制事务,没必要去修改原本的自动提交的机制,开启所有事务

  • 扩展:事务处理的支持是有条件的;存储引擎必须为InnoDB

示例如下:
(1)手动事务:启用事务转账,成功提交事务

# 开启事务
start transaction;

# Tom扣钱
update t_52 set account = account - 1000 where id  = 1;

# Lucy收钱
update t_52 set account = account + 1000 where id  = 2;

# 提交事务
commit;

(2)手动事务:启用事务转账,成功提交事务(回滚点)

# 开启事务
start transaction;

# Tom扣钱
update t_52 set account = account - 1000 where id= 1;

# 设置回滚点
savepoint sp1;

# Lucy收钱
update t_52 set account = account + 10000 where id= 2;

# 操作失败回到回滚点
rollback to sp1;

# Lucy收钱
update t_52 set account = account + 1000 where id= 2;

# 提交事务
commit;

(3)自动事务

  • Mysql默认是自动提交事务的:所以事务一旦发生就会立即写入到数据表(不能多个事务一起完成任务)
show variables like 'autocommit';
  • 关闭自动提交事务(当前设置级别用户级:当前用户档次连接有效)
set autocommit = 0;	
  • 手动提交事务
insert into t_52 values(null,'Liu',1000);
commit;

3、事务特点

事务特点:事务处理具有ACID四大特性

  • 原子性(Atomicity ):一个事务操作是一个整体,不可拆分,要么都成功,要么都失败
  • 一致性(Consistency):事务执行之前和执行之后都必须处于一致性状态,数据的完整性没有被破坏(事务逻辑的准确性)
  • 隔离性(Isolation ):事务操作过程中,其他事务不可见
  • 持久性(Durability ):事务一旦提交,结果不可改变

事务锁:当一个事务开启时,另外一个事务是不能对当前事务锁占用的数据进行操作的

  • 行锁:当前事务只占用了一行(id精确检索数据),那么其他事务可以操作其他行数据
  • 表锁:当前事务占用了整张表(like扫码整个表),那么其他事务对整张表都不能操作

脏读:一个事务在对某个数据进行操作但尚未提交,而另外一个事务读到了这个“历史”数据其实已经被修改

三、预处理

1、预处理

预处理:prepare statement,一种预先编译SQL指令的方式(然后命令执行)

  • 预处理是将要执行的SQL指令先发送给服务器编译,然后通过指令执行
    • 发送预处理:prepare 预处理名字 from '要执行的SQL指令'
    • 执行预处理:execute 预处理名字
  • 预处理管理
    • 预处理属于会话级别:即当前用户当次连接有效(断开会被服务器清理掉)
    • 删除预处理:deallocate | drop prepare 预处理名字

示例:查询学生的SQL指令需要重复执行很多次

# 普通操作
select * from t_42;

# 预处理操作:发送预处理
prepare p1 from 'select * from t_42';

# 预处理操作:执行预处理
execute p1;

# 删除预处理
deallocate  prepare p1;
  • 预处理的作用
    • 性能优化上:
      • 效率优化:同样的SQL不用每次都进行编译(编译耗时)
        • 普通处理:每次都需要编译
        • 预处理:编译一次
      • 网络传输优化:复杂的SQL指令只需要传输一次
        • 普通处理:每次都需要网络传输SQL指令
        • 预处理:传输一次SQL指令,以后都是执行指令
    • 安全上:有效防止SQL注入(外部通过数据的特殊使用使得SQL的执行方式改变)
  • 对比
    • 普通处理:直接发送给服务器执行(容易出现SQL注入)
    • 预处理:发送的是结构,数据是后期执行传入(传入协议不一样,数据安全性高)

2、预处理传参

预处理传参:在执行预处理的时候传入预处理需要的可变数据

  • 一般预处理都不会是固定死的SQL指令,而是具有一些数据可变的执行(条件)

    • 可变数据的位置使用占位符 ? 占位
    prepare 预处理名字 from `预处理指令 变化部分使用?替代`
    
  • 在执行预处理时将实际数据传进去代替占位符执行SQL

    • 数据存储到变量(预处理传入的值必须是变量保存的)
    set @变量名 = 值
    
    • 使用using关键字传参
    execute 预处理名字 using @变量名
    
    • 数据传入的顺序与预处理中占位符的顺序一致
  • 适用于增删改查各种指令

  • 如果预处理指令不是在一次连接中重复使用,则预处理反而会降低效率

四、视图

1、视图

视图:view,一种由select指令组成的虚拟表;为视图提供数据的表叫做基表。

# 创建视图
create view 视图名字 as select指令;

# 访问视图:一般都是查询
select */字段名 from 视图名字;
  • 视图有结构,但不存储数据
    • 结构:select选择的字段
    • 数据:访问视图时执行的select指令
  • 视图的目的
    • 方便提供全面数据,不会在数据库产生数据冗余
    • 数据安全:视图本质是来源于数据基表,但对外可保护基本的数据结构

有些复杂的SQL经常用到,如多张表的连表操作:可以利用视图实现

# 院系表
create table t_53(
	id int primary key auto_increment,
    name varchar(50) not null
)charset utf8;
insert into t_53 values(null,'语言系'),(null,'考古系');

# 专业表
create table t_54(
    id int primary key auto_increment,
    name varchar(50) not null,
    s_id int not null comment '学院id'
)charset utf8;
insert into t_54 values(null,'English',1),(null,'Chinese',1);

# 学生表
create table t_55(
	id int primary key auto_increment,
    name varchar(50) not null,
    s_id int not null comment '专业Id'
)charset utf8;
insert into t_55 values(null,'Lilei',2),(null,'Mark',2),(null,'Tony',1);

# 获取所有学生的明细信息
select stu.*,sub.name as sub_name,sub.s_id as sch_id,sch.name as sch_name from t_55 as stu left join t_54 sub on stu.s_id = sub.id left join t_53 sch on sub.s_id = sch.id;

# 以视图保存这类复杂指令,后续可以直接访问视图
create view v_student_detail as select stu.*,sub.name as sub_name,sub.s_id as sch_id,sch.name as sch_name from t_55 as stu left join t_54 sub on stu.s_id = sub.id left join t_53 sch on sub.s_id = sch.id;

select * from v_student_detail;

2、视图管理

  • 视图查看:显示视图结构和具体视图信息
show tables;	# 查看全部视图
show create table/view 视图名字;	# 查看视图创建指令
desc 视图名字;	 # 查看视图结构
  • 视图修改:更改视图逻辑
# 更改视图
alter view 视图名 as 新的查询指令;
create or replace view 视图名 as 新的查询指令;	# 创建新的或者替换新的
  • 视图删除
drop view 视图名; 

3、视图数据操作

  • 直接对视图进行写操作(增删改)然后实现基表数据的变化
  • 视图操作条件
    • 多基表视图:不允许操作(增删改都不行)
    • 单基表视图:允许增删改
      • 新增条件:视图的字段必须包含基表中所有不允许为空的字段
    • with check option:操作检查规则
      • 默认不需要这个规则(创建视图时指定)
      • 增加此规则:视图的数据操作后,要保证该视图还能把通过视图操作的数据查出来(否则失败)

4、视图算法

  • 指视图在执行过程中对于内部的select指令的处理方式

  • 视图算法在创建视图时指定

create ALGORITHM = 算法 view 视图名字 as select指令;
  • 视图算法一共有三种
    • undefined:默认的,未定义算法,即系统自动选择算法
    • merge:合并算法,就是将视图外部查询语句跟视图内部select语句合并后执行,效率高(系统优先选择)
    • temptable:临时表算法,即系统将视图的select语句查出来先得出一张临时表,然后外部再查询(temptable算法视图不允许写操作),通常视图中如果出现了order by排序的话,就要考虑使用

五、数据备份与还原

备份:backup,将数据或者结构按照一定的格式存储到另外一个文件中,以保障阶段数据的完整性和安全性;

还原:restore,在当前数据出问题的情况下,将之前备份的数据替换掉当前数据,保证系统的持续、正确的运行。

1、表数据备份

单独针对表里的数据部分进行备份(数据导出)

  • 将数据从表中查出,按照一定格式存储到外部文件
    • 字段格式化:fields
      • terminated by:字段数据结束后使用的符号,默认是空格
      • enclosed by:字段数据包裹,默认什么都没有
      • escaped by:特殊字符的处理,默认是转义
    • 行格式化:lines
      • terminated by:行结束符号,默认是\n,自动换行
      • starting by:行开始符号,默认没有
select 字段列表|*  into outfile 外部文件路径 
	[fields terminated by 格式 enclosed by 格式]
	[lines terminated by 格式 starting by 格式]
from 数据表;
  • 表数据备份不限定数据的来源是一张表还是多张表(可以连表)

2、表数据还原

符合数据表结构的数据导入到数据表中(数据导入)

  • 将一定格式的数据按照一定的解析方式解析成符合表字段格式的数据导入到数据表;字段处理和行处理。
load data infile '数据文件所在路径' into table 表名
	[fields terminated by 格式 enclosed by 格式]
	[lines terminated by 格式 starting by 格式]
	[(字段列表)];	# 如果是部分表字段,那么必须将字段列表放到最后
  • 数据文件来源:表数据备份的数据文件;外部获取或者制作的符合格式的数据。

3、文件备份

直接对数据表进行文件保留,属于物理备份。

  • 操作简单,直接将数据表(或者数据库文件夹)进行保存迁移
  • MySQL中不同表存储引擎产生的文件不一致,保存手段也不一致
    • InnoDB:表结构文件在ibd文件中,数据和索引存储在外部统一的ibdata文件中(Mysql7以前话是frm后缀)
    • MyIsam:每张表的数据、结构和索引都是独立文件,直接找到三个文件迁移即可
  • 文件备份方式非常占用磁盘空间

(1)MyIsam表的文件备份:找到三个文件,复制迁移;适合文件备份,独立表迁移,因为其存储引擎表文件独立,不关联其他表。

  • sdi:表结构文件; MYI:索引文件; MYD:数据文件

(2)InnoDB表的文件备份:找到两个文件,复制迁移;适合整库迁移。

  • ibd:表结构文件; ibdata:所有InnoDB数据文件

4、文件还原

利用备份的文件,替换出现问题的文件,还原到备份前的良好状态。

  • 直接将备份的文件放到对应的位置即可

  • 文件还原影响

    • MyIsam存储引擎:单表备份,单表还原,不影响其他任何数据
    • InnoDB存储引擎:单表结构,整库数据,只适合整库备份还原,否则会影响其他InnoDB存储表

5、SQL备份

将数据库的数据以SQL指令的形式保存到文件当中,属于逻辑备份。

  • 利用Mysqldump.exe客户端实现备份

  • 将备份目标(数据表)以SQL指令形式,从表的结构、数据和其他信息保存到文件

    mysqldump.exe -h -P -u -p [备份选项] 数据库名字 [数据表列表] > SQL文件路径

  • 备份选项很多,常见的主要是数据库的备份多少

    • 全库备份:--all-databases 所有数据库的所有表,也不需要指定数据库名字
    • 单库备份:[--databases] 数据库 指定数据库里的所有表(后面不要给表名)
    • 部分表(单表)备份:数据库名字 表1[ 表2...表N]
  • 比较耗费时间和占用性能,建议在闲时进行(用户不活跃时)

  • 可以根据数据表的重要性进行频次区分备份

6、SQL还原

在需要用到SQL备份数据时,想办法让SQL执行,从而实现备份数据的还原。

  • 使用Mysql.exe进行操作
    mysql.exe -h -P -u -p [数据库名字] < SQL文件路径
  • 在进入到数据库之后利用SQL指令还原
source SQL文件路径;
  • 不能百分百保证数据库的数据不受影响
  • SQL备份通常不具有实时性(一般都会有时间间断)

备份及还原总结:

  • 表数据备份与还原:适用于数据导出和导入,数据具有结构,但是不包含字段和类型
  • 文件备份与还原:简洁方便,但是需要区分存储引擎InnoDB和MyIsam(InnoDB不适合进行文件备份)
  • SQL备份与还原:不限定存储引擎,随时随地可以备份,不过备份和还原的效率都比较低(完整备份)

六、用户管理

1、账号管理

根据项目的需求设置和管理账号

  • 账号是权限依赖的对象,先有账号才有权限
  • MySQL中账号的组成分为两个部分:用户名 @ 主机地址(root@localhost)
    • 用户名为用户登录时的名字
    • 主机地址:是允许账号所在客户端的访问的客户端IP(如上述root只能在服务器本机通过客户端访问)
  • 账号管理
    • 创建账号:create user 用户名@主机地址 identified by '明文密码';
    • 删除账号:drop user 用户名@主机地址

2、权限管理

对账号进行权限的支持与回收

  • 账号创建之初除了登录是没有其他操作权限的

  • 账号的管理通常需要配合权限的使用

    • 赋权:给账号绑定相应的权限 grant 权限列表 on 数据库|*.数据表|* to 用户名@主机地址
    • 回收:将账号已有的权限回收 revoke 权限列表 on 数据库|*.数据表|* from 用户名@主机地址
    • 刷新权限:flush privileges
    • 查看权限:show grants for 用户名@主机地址
  • MySQL提供的权限列表

Privilege Grant Table Column Context
ALL [PRIVILEGES] Synonym for “all privileges” Server administration
ALTER Alter_priv Tables
ALTER ROUTINE Alter_routine_priv Stored routines
CREATE Create_priv Databases, tables, or indexes
CREATE ROLE Create_role_priv Server administration
CREATE ROUTINE Create_routine_priv Stored routines
CREATE TABLESPACE Create_tablespace_priv Server administration
CREATE TEMPORARY TABLES Create_tmp_table_priv Tables
CREATE USER Create_user_priv Server administration
CREATE VIEW Create_view_priv Views
DELETE Delete_priv Tables
DROP Drop_priv Databases, tables, or views
DROP ROLE Drop_role_priv Server administration
EVENT Event_priv Databases
EXECUTE Execute_priv Stored routines
FILE File_priv File access on server host
GRANT OPTION Grant_priv Databases, tables, or stored routines
INDEX Index_priv Tables
INSERT Insert_priv Tables or columns
LOCK TABLES Lock_tables_priv Databases
PROCESS Process_priv Server administration
PROXY See proxies_priv table Server administration
REFERENCES References_priv Databases or tables
RELOAD Reload_priv Server administration
REPLICATION CLIENT Repl_client_priv Server administration
REPLICATION SLAVE Repl_slave_priv Server administration
SELECT Select_priv Tables or columns
SHOW DATABASES Show_db_priv Server administration
SHOW VIEW Show_view_priv Views
SHUTDOWN Shutdown_priv Server administration
SUPER Super_priv Server administration
TRIGGER Trigger_priv Tables
UPDATE Update_priv Tables or columns
USAGE Synonym for “no privileges” Server administration
  • DBA用户通常可以分配整个数据库所有库的权限:all on *.*

  • 项目管理级别的用户可以针对所负责项目的权限:all on 数据库.*(多个项目分配多次)

  • 项目开发者用户可以针对所负责项目模块的权限:权限列表 on 数据库.表名/*(如果是跨项目分配多次)

  • 常用的开发者权限有:

    • create、alter、drop:库、表结构操作
    • insert、select、update、delete:数据操作
    • references:外键权限
    • index:索引
  • 扩展:可以直接使用赋权创建新用户(MySQL7以上不允许这么操作)

grant select on db_2.* to `user`@`localhost` with grant option;

3、角色管理

根据角色来分配权限,然后用户只需要关联角色即可(分配角色)(Mysql8以后有)

  • 角色的存在可以更方便的用户维护多个具有相同权限的用户(核心价值)
  • 角色相关操作和语法
    • 创建角色:create role 角色名字1[,角色名字2,...角色名字N](可批量创建)
    • 分配权限:grant 权限列表 on 数据库|*.数据表|* to 角色名字
    • 绑定角色:grant 角色名字 to 用户名@主机地址
    • 撤销角色:revoke 角色名字 from 用户名@主机地址
    • 回收角色权限:revoke 权限列表 on 数据库|*.数据表|* from 角色名字
    • 删除角色:drop role 角色名字1[,角色名字2,...角色名字N]

你可能感兴趣的:(MySQL)