本篇总结数据库相关安全性的知识点,包含外键约束、事务管理、预处理、视图、数据备份还原和用户管理 ~
首先,安全管理就是用各种方式来确保数据库的安全和数据的安全。我们经常见到表情包,某公司程序员删库跑路…
那么如果有用户管理,就可以通过权限限制其没有权限删除;如果有数据备份,即便数据删除,也可以很快的实现数据还原,减小损失。
然而,数据库安全的维度有很多,比如:管理安全~用户、权限、备份还原等; 结构安全~外键、视图、事务等; 执行层~预处理。
外键: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;
外键约束:当表建立外键关系后,外键就会对主表(外键指向的表)和子表(外键所在的表)里的数据产生约束效果
外键管理:在表创建后期维护外键
alter table 表名 add [constraint `外建名`] foreign key(外键字段) references 表名(主键) [on 外键约束]
alter table 表名 drop foreign key 外键名;
事务:要做的某个事情
计算机中的事务是指某个程序执行单元(写操作)
事务安全:当事务执行后,保障事务的执行是有效的,而不会导致数据错乱
事务安全通常针对的是一连串操作(多个事务)而产生的统一结果
MySQL中默认的写操作是直接写入的
例如银行转账:从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;
事务安全原理
事务处理:利用自动或者手动方式实现事务管理
自动事务处理:系统默认,操作结束直接同步到数据表(事务关闭状态)
手动事务处理
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)自动事务
show variables like 'autocommit';
set autocommit = 0;
insert into t_52 values(null,'Liu',1000);
commit;
事务特点:事务处理具有ACID四大特性
事务锁:当一个事务开启时,另外一个事务是不能对当前事务锁占用的数据进行操作的
脏读:一个事务在对某个数据进行操作但尚未提交,而另外一个事务读到了这个“历史”数据其实已经被修改
预处理:prepare statement,一种预先编译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指令,而是具有一些数据可变的执行(条件)
?
占位prepare 预处理名字 from `预处理指令 变化部分使用?替代`
在执行预处理时将实际数据传进去代替占位符执行SQL
set @变量名 = 值
execute 预处理名字 using @变量名
适用于增删改查各种指令
如果预处理指令不是在一次连接中重复使用,则预处理反而会降低效率
视图:view,一种由select指令组成的虚拟表;为视图提供数据的表叫做基表。
# 创建视图
create view 视图名字 as select指令;
# 访问视图:一般都是查询
select */字段名 from 视图名字;
有些复杂的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;
show tables; # 查看全部视图
show create table/view 视图名字; # 查看视图创建指令
desc 视图名字; # 查看视图结构
# 更改视图
alter view 视图名 as 新的查询指令;
create or replace view 视图名 as 新的查询指令; # 创建新的或者替换新的
drop view 视图名;
指视图在执行过程中对于内部的select指令的处理方式
视图算法在创建视图时指定
create ALGORITHM = 算法 view 视图名字 as select指令;
备份:backup,将数据或者结构按照一定的格式存储到另外一个文件中,以保障阶段数据的完整性和安全性;
还原:restore,在当前数据出问题的情况下,将之前备份的数据替换掉当前数据,保证系统的持续、正确的运行。
单独针对表里的数据部分进行备份(数据导出)
select 字段列表|* into outfile 外部文件路径
[fields terminated by 格式 enclosed by 格式]
[lines terminated by 格式 starting by 格式]
from 数据表;
将符合数据表结构的数据导入到数据表中(数据导入)
load data infile '数据文件所在路径' into table 表名
[fields terminated by 格式 enclosed by 格式]
[lines terminated by 格式 starting by 格式]
[(字段列表)]; # 如果是部分表字段,那么必须将字段列表放到最后
直接对数据表进行文件保留,属于物理备份。
(1)MyIsam表的文件备份:找到三个文件,复制迁移;适合文件备份,独立表迁移,因为其存储引擎表文件独立,不关联其他表。
(2)InnoDB表的文件备份:找到两个文件,复制迁移;适合整库迁移。
利用备份的文件,替换出现问题的文件,还原到备份前的良好状态。
直接将备份的文件放到对应的位置即可
文件还原影响
将数据库的数据以SQL指令的形式保存到文件当中,属于逻辑备份。
利用Mysqldump.exe客户端实现备份
将备份目标(数据表)以SQL指令形式,从表的结构、数据和其他信息保存到文件
mysqldump.exe -h -P -u -p [备份选项] 数据库名字 [数据表列表] > SQL文件路径
备份选项很多,常见的主要是数据库的备份多少
--all-databases
所有数据库的所有表,也不需要指定数据库名字[--databases] 数据库
指定数据库里的所有表(后面不要给表名)数据库名字 表1[ 表2...表N]
比较耗费时间和占用性能,建议在闲时进行(用户不活跃时)
可以根据数据表的重要性进行频次区分备份
在需要用到SQL备份数据时,想办法让SQL执行,从而实现备份数据的还原。
mysql.exe -h -P -u -p [数据库名字] < SQL文件路径
source SQL文件路径;
根据项目的需求设置和管理账号
create user 用户名@主机地址 identified by '明文密码';
drop user 用户名@主机地址
对账号进行权限的支持与回收
账号创建之初除了登录是没有其他操作权限的
账号的管理通常需要配合权限的使用
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 数据库.表名/*(如果是跨项目分配多次)
常用的开发者权限有:
扩展:可以直接使用赋权创建新用户(MySQL7以上不允许这么操作)
grant select on db_2.* to `user`@`localhost` with grant option;
根据角色来分配权限,然后用户只需要关联角色即可(分配角色)(Mysql8以后有)
create role 角色名字1[,角色名字2,...角色名字N]
(可批量创建)grant 权限列表 on 数据库|*.数据表|* to 角色名字
grant 角色名字 to 用户名@主机地址
revoke 角色名字 from 用户名@主机地址
revoke 权限列表 on 数据库|*.数据表|* from 角色名字
drop role 角色名字1[,角色名字2,...角色名字N]