MySQL 数据库安全管理
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 数据库安全管理相关的知识,希望对你有一定的参考价值。
安全管理:用各种方式来确保数据库的安全和数据的安全
1、安全管理是每一个接触数据库的人都应该考虑的问题,尤其是DBA(数据库管理员)
2、数据库安全的维度有很多
- 管理安全:用户、权限、备份还原等
- 结构安全:外键、视图、事务等
- 执行层:预处理
一、外键约束
外键:foreign key,表中指向外部表主键的字段定义成外键
- 外键必须要通过语法指定才能称之为外键
[constraint 外键名] foreign key(当前表字段名) references 外部表(主键字段)
- 外键构成条件:
- 外键字段必须与对应表的主键字段类型一致
- 外键字段本身要求是一个索引(创建外键会自动生成一个索引)
- 一张表可以有多个外键,但是一个字段只能产生一个外键
示例
1、创建专业表和学生表,学生表中的专业id指向专业表id
create table t_7(
id int primary key auto_increment,
name varchar(50) not null unique
)charset utf8;
create table t_8(
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_7(id)
)charset utf8;
2、外键可以不指定名字,系统会自动生成
create table t_9(
id int primary key auto_increment,
name varchar(50) not null,
c_id int,
foreign key(c_id) references t_7(id)
)charset utf8;
外键约束:当表建立外键关系后,外键就会对主表(外键指向的表)和子表(外键所在的表)里的数据产生约束效果
-
外键约束的是写操作(默认操作)
- 新增:子表插入的数据对应的外键必须在主表存在
- 修改:主表的记录如果在子表存在,那么主表的主键不能修改(主键不能修改)
- 删除:主表的记录如果在子表存在,那么主表的主键不能删除
-
外键约束控制:外键可以在定义时控制外键的约束作用
- 控制类型:
- on update:父表更新时子表的表现
- on delete:父表删除时子表的表现
- 控制方式:
- cascade:级联操作,父表操作后子表跟随操作
- set null:置空操作,父表操作后,子表关联的外键字段置空
- restrict:严格模式,不允许父表操作 (默认)
- no action:子表不管
- 控制类型:
-
外键约束对子表和父表都有约束
- 子表约束:子表不能插入父表不存在的外键
- 父表约束
- 更新约束(默认不允许)
- 删除约束(默认不允许)
- 一般约束
- 级联更新
- 删除置空
-
外键约束增强了数据的安全性和可靠性,但是会增加程序对于数据的不可控性,所以是实际开发中一般会通过程序逻辑控制来保证数据的完整性和安全性,外界使用较少
示例
1、子表不能插入主表不存在的数据
insert into t_7 values(null,'Tony',2); # 错误
insert into t_7 values(null,'English');
insert into t_8 values(null,'Peny',1);
2、默认的外键产生后,主键不能更新被关联的主键字段或者删除被关联的主键记录
# 错误
update t_7 set id = 2;
delete from t_7 where id = 1;
3、限制外键约束,一般使用更新级联,删除置空
- on update cascade:更新级联
- on delete set null:删除置空
create table t_0(
id int primary key auto_increment,
name varchar(50) not null unique
)charset utf8;
create table t_1(
id int primary key auto_increment,
name varchar(50) not null,
c_id int, # 如果要允许置空,就不能not null
foreign key(c_id) references t_50(id) on update cascade on delete set null
)charset utf8;
insert into t_0 values(null,'Chinese'),(null,'Computer');
insert into t_1 values(null,'Tony',1),(null,'Petter',2);
- 子表依然不允许插入父表不存在的外键
- 但是可以插入外键为Null的数据
# 错误
insert into t_1 values(null,'Lilei',3);
insert into t_1 values(null,'Lilei',NULL); # OK
- 父表的更新(主键)会让关联的外键自动级联更新
update t_0 set id = 3 where id = 1;
- 父表的删除会让关联的外键自动自动置空
delete from t_0 where id = 3;
外键管理:在表创建后期维护外键
外键的使用最好的创建表结构的时候就维护好,后期的维护对子表数据有要求
-
新增外键:
alter table 表名 add [constraint 外建名] foreign key(外键字段) references 表名(主键) [on 外键约束]
-
删除外键:
alter table 表名 drop foreign key 外键名;
-
更新外键:先删除后新增
示例
1、删除外键
alter table t_1 drop foreign key t_1_ibfk_1; # 系统生成的外键
2、追加外键
alter table t_1 add constraint t_1_0 foreign key(c_id) references t_0(id);
- 注意:追加外键需要保证外键字段里的值要么为Null,要么在父表中都能找到
二、事务安全
事务:要做的某个事情
-
计算机中的事务是指某个程序执行单元(写操作)
-
事务安全:当事务执行后,保障事务的执行是有效的,而不会导致数据错乱
-
事务安全通常针对的是一连串操作(多个事务)而产生的统一结果
-
事务的目的就是为了保障连续操作的一致性,保证结果的完整性
-
mysql中默认的写操作是直接写入的
- 执行写操作SQL
- 同步到数据表
示例
银行转账:从A账户转账到B账户
创建数据表
create table t_2(
id int primary key auto_increment,
name varchar(50) not null,
account decimal(10,2) default 0.00
)charset utf8;
insert into t_2 values(null,'Tom',10000),(null,'Lucy',100);
转账:Tom向Lucy转账,一定是分为两步
# Tom扣钱
update t_2 set account = account - 1000 where id = 1;
# Lucy收钱
update t_2 set account = account + 1000 where id = 2;
- 以上两步必须都成功转账才能叫成功
- 两步操作无法确保哪一步会出问题(尤其是第二步)
- 为了保障两步都成功才能叫事务安全
事务安全原理:
事务安全是在操作前告知系统,接下来所有的操作都暂不同步到数据表,而是记录到事务日志,等后续所有操作都成功,再一并同步到数据表中;否则取消所有操作
以上述转账为例:
事务处理:利用自动或者手动方式实现事务管理
-
自动事务处理:系统默认,操作结束直接同步到数据表(事务关闭状态)
- 系统控制:变量 autocommit(值为ON,自动提交)
-
手动事务处理:
- 开启事务:
start transaction
- 关闭事务
- 提交事务:
commit
(同步到数据表同时清空日志数据) - 回滚事务:
rollback
(清空日志数据)
- 提交事务:
- 开启事务:
-
事务回滚:在长事务执行中,可以在某个已经成功的节点处设置回滚点,后续回滚的话可以回到某个成功点
- 设置回滚点:
savepoint 回滚点名字
- 回滚到回滚点:
rollback to 回滚点名字
- 设置回滚点:
-
事务处理通常都会使用手动控制事务,没必要去修改原本的自动提交的机制,开启所有事务
-
扩展:事务处理的支持是有条件的
- 存储引擎需要为 InnoDB
示例
1、手动事务:启用事务转账,成功提交事务
# 开启事务
start transaction;
# Tom扣钱
update t_2 set account = account - 1000 where id = 1;
# Lucy收钱
update t_2 set account = account + 1000 where id = 2;
# 提交事务
commit;
2、手动事务:启用事务转账,成功提交事务(回滚点)
# 开启事务
start transaction;
# Tom扣钱
update t_2 set account = account - 1000 where id= 1;
# 设置回滚点
savepoint sp1;
# Lucy收钱
update t_2 set account = account + 10000 where id= 2;
# 操作失败回到回滚点
rollback to sp1;
# Lucy收钱
update t_2 set account = account + 1000 where id= 2;
# 提交事务
commit;
3、自动事务
- Mysql默认是自动提交事务的:所以事务一旦发生就会立即写入到数据表(不能多个事务一起完成任务)
show variables like 'autocommit';
- 关闭自动提交事务(当前设置级别用户级:当前用户档次连接有效)
set autocommit = 0;
- 手动提交事务
insert into t_2 values(null,'Liu',1000);
commit;
事务特点:事务处理具有 A C I D 四大特性
- 原子性(Atomicity ):一个事务操作是一个整体,不可拆分,要么都成功,要么都失败
- 一致性(Consistency):事务执行之前和执行之后都必须处于一致性状态,数据的完整性没有被破坏(事务逻辑的准确性)
- 隔离性(Isolation ):事务操作过程中,其他事务不可见
- 持久性(Durability ):事务一旦提交,结果不可改变
事务锁:当一个事务开启时,另外一个事务是不能对当前事务锁占用的数据进行操作的
- 行所:当前事务只占用了一行(id精确检索数据),那么其他事务可以操作其他行数据
- 表所:当前事务占用了整张表(like扫码整个表),那么其他事务对整张表都不能操作
脏读:一个事务在对某个数据进行操作但尚未提交,而另外一个事务读到了这个“历史”数据其实已经被修改
三、预处理
预处理:prepare statement,一种预先编译SQL指令的方式(然后命令执行)
- 预处理不同于直接处理,就是把要执行的结构(SQL指令)提前发送给服务器端,服务器进行编译但不执行,等待执行指令后才执行
- 发送预处理:
prepare 预处理名字 from '要执行的SQL指令'
- 执行预处理:
execute 预处理名字
- 发送预处理:
- 预处理管理
- 预处理属于会话级别:即当前用户当次连接有效(断开会被服务器清理掉)
- 删除预处理:
deallocate | drop prepare 预处理名字
预处理
示例
1、查询学生的SQL指令需要重复执行很多次
# 普通操作
select * from t_2;
# 预处理操作:发送预处理
prepare p1 from 'select * from t_2';
# 预处理操作:执行预处理
execute p1;
# 删除预处理
deallocate prepare p1;
预处理原理:
普通处理和预处理对比: