10.0 安全与保护概述
造成数据库的数据不正确,甚至被破坏的主要原因有
- 自然灾害的破坏
-
- 如火灾、地震、洪水等
- 人为的恶意破坏
-
- 如计算机病毒或未被授权人有意篡改数据等
- 对数据库数据的更新操作有误
-
- 如操作时输入的数据有误或存取数据库的应用程序有错等
- 数据库的并发操作引起数据的不一致性
-
- 如两个进程同时对同一个数据进行更新操作
- 数据库系统的软、硬件故障造成数据被破坏
DBMS层所提供的数据库安全和保护功能:
- 安全性(security)保护,即防止非法用户对数据库的非法使用,以避免数据的泄露、篡改或破坏
- 完整性(integrity)保护,即保证数据的正确性和一致性
- 并发控制(concurrent control),即保证多用户能共享数据库,并维护数据的一致性
- 数据库恢复(database recovery),即在系统失效后的数据库恢复,配合定时备份数据库,使数据库不丢失数据。中
10.1 数据库的安全性保护
用户鉴别
- DBMS鉴别一个用户是否为合法用户是DBMS提供的最外层安全性保护措施。
- DBMS提供了一定的工具和命令,让DBA创建和定义合法用户,并对每个合法用户赋予一定的角色。
- MySQL是一个多用户的数据库管理系统,它提供了功能强大的访问控制系统,以此来确保MySQL服务器的安全访问,即它可以为不同用户指定不同的访问权限,从而进一步减少数据泄露或被损坏的风险。
- 用户的种类
-
- root用户,超级管理员,拥有所有权限
- 普通用户,只能拥有被授予的权限
- 查看用户信息
-
- SELECT user, host FROM mysql.user; #只有root才能查看
- SELECTUSER(;#查看当前用户(反映连接身份)
- SELECTCURRENT USERO;#查看当前用户(反映权限身份)

- 创建用户
- 登录MySQL服务器
- 修改用户名
- 删除用户
- 修改当前用户密码
- 修改其他用户密码
- 密码过期策略
-
- 在MySQL中,数据库管理员可以手动设置账号密码过期,也可以建立一个自动密码过期策略
- 过期策略可以是全局的,也可以为每个账号设置单独的过期策略
存取权限控制
权限级别
- 用户权限(user):其和MySQL中所有的数据库相关
- 数据库权限(db):其和一个具体的数据库中的所有表相关
- 表权限(tables_priv):其和一个具体表中的所有数据相关
- 列权限(columns_priv):其和表中的一个具体列相关
授权粒度
- 是衡量授权机制是否灵活的一个重要指标
- 授权粒度越细,授权子系统就越灵活,能够提供的安全性就越完善,但数据字典会变得大而复杂,系统定义与检查权限的开销也会随之增大。
user表,是MySQL中非常重要的一个权限表(用户层权限)
- 范围列:包括host字段、user字段和authentication_string字段。
- 权限列:决定了用户的权限,表示了在全局范围内允许对数据和数据库进行的操作。
- 安全列:都是和加密、标识用户、授权插件相关的字段。
- 资源控制列:用来限制用户使用的资源。
- user字段,表示用户名
-
- 同一用户通过不同方式连接的权限是不一样的
- host字段,表示连接类型
-
- %,表示所有远程通过TCP方式的连接。
- localhost,本地方式通过命令行方式的连接
- IP地址,通过指定IP地址进行的TCP方式的连接
- 机器名,通过指定网络中的机器名进行的TCP方式的连接。
- ::1,IPv6的本地IP地址,等同于IPv4的127.0.0.1
- authentication_string字段,用户密码。
-
- 存储用户密码哈希值的核心字段
- db表(数据库层权限)
-
- 用户列:包括user字段、host字段和db字段,表示从某个主机连接某个用户对某个数据库的操作权限。
- 权限列:决定了用户是否具有指定的权限。

tables priv表(表层权限)
- 用户列:包括host字段、user字段、db字段和Table name字段。
- Grantor列:表示修改该记录的用户。
- Timestamp列:表示修改该记录的时间。
- Table priv列:表示对象的操作权限。包括Select、Insert、Update、Delete、Create、 Drop、 Grant、 References、Index利Alter.
- Column_priv列:表示对表中的列的操作权限。包括Select、Insert、Update和References。

columns priv表(字段层权限)
- 用户列:包括host字段、user字段、db字段、Table name字段和Column name字段。
- Timestamp列:表示修改该记录的时间。
- Column_priv列:表示对表中的列的操作权限。包括Select、Insert、Update利References。

procspriv表,保存对存储过程和存储函数设置操作权限
- 用户列:包括host字段、user字段、db字段
- Routine_name列:存储过程名称
- Routine_type列:存储过程类型,存储过程or存储函数
- Grantor列:表示修改该记录的用户
- Timestamp列:表示修改该记录的时间。
- Proc priv列:表示对存储过程的操作权限。包括Execute,Alter Routine,Grant.
权限管理

授予权限

ON database.table,ON后面跟的是该权限的适用对象
- 全局权限,适用于一个给定服务器中的所有数据库,可用*.*表示。
- 数据库权限,适用于一个给定数据库中的所有目标,可用database.*表示
- 表权限,适用于一个具体表中的所有列,可用database.tab下表示
- 列权限,适用于表中的具体列,此时在权限后面把具体列表示出来即可
授予权限
例:将Students表中Sno字段、Sname字段的查询权限授予用户zhang3.
- GRANT SELECT(Sno, Sname) ON jxdb.Students TO zhang3@localhost;
- FLUSH PRIVILEGES;
- mysql -u zhang3@localhost -p jxdb
- SELECT Sno, Sname FROM Students;
- SELECT * FROM Students;
撤销权限
REVOKE priv_type[(column_list)] ON database.table
FROM user[,...n]
例:撤销用户zhang3查询Students表中Sname字段的权限,撤销用户kangshifu的所有权限
REVOKE SELECT(Sname) ON jxdb.Students FROM zhang3@localhost;
REVOKE ALL,GRANT OPTION FROM kangshifu@localhost;
FLUSH PRIVILEGES;
角色管理
- 目的是方便管理拥有相同权限的用户。

创建角色
- CREATE ROLE 'role_name'[@'host_name'][..n];
- 例:
CREATE ROLE 'manager'@'localhost';
给角色赋予权限
- GRANT privileges ON table_name TO 'role_name'[@'host_name'];
SHOW PRIVILEGES;
查看角色的权限
- SHOW GRANTS FOR 'role_name';
回收角色的权限
- REVOKE privileges ON table name FROM'role name';
- FLUSH PRIVILEGES;
删除角色
- DROP ROLE 'role_name';
- 注意:如果你删除了角色,那么用户也就失去了通过这个角色所获得的所有权限
给用户赋予角色
- 角色创建并授权后,要赋给用户并处于激活状态才能发挥作用
- 1.授权 GRANT rolename [,...n]TO username;
- 2.激活 SET DEFAULT ROLE ALL TO username;
撤销用户的角色
- REVOKE rolename FROM username;
视图机制
-

-
通过视图机制可限制用户使用数据的范围,从而自动地对数据提供一定程度的安全保护。
-
视图(外模式)
-
- 视图是查询结果的关系,是被存储的查询定义,视图的属性名由子查询确定

-

-
创建视图的格式为:

- 组成视图的属性列名要么全部省略要么全部指定。但在下列三种情况下必须明确指定组成视图的所有列名:
-
- 某个目标列不是单纯的属性名,而是集函数或列表达式。
- 多表连接导出的视图中有几个同名列作为该视图的属性列名。
- 需要在视图中为某个列使用新的更合适的名字
- 例:建立学院号为16的学生的视图,并要求进行修改和插入操作时仍需保证该视图只有学院号为16的学生,视图的属性名为Sno,Sname, Sbirth, Dno, Mno
- 例:建立所有学生的基本信息、选课信息及相关课程信息的视图

- 例:定义一个反应学生出生年份的视图

- 对于已经定义的视图,用户应用SELECT语句,就像查询基本表一样查询视图
- 例8:基于视图VIEWStuInfo2建立学生的学号(Sno)、姓名(Sname)、选修课程名(Cname)及成绩(Grade)的视图

- 删除视图的语句格式为:
-
- DROP VIEW<视图名>
- 说明:视图删除后视图的定义将从数据字典中删除。但是由该视图导出的其它视图定义仍在数据字典中,不过该视图已失效。用户使用时就会出错,要用DROPVIEW语句显式将它们一一删除
- 更新视图
-
- 指通过视图来插入(INSERT)、删除(DELETE)和修改(UPDATE)数据。由于视图是不实际存储数据的虚拟表,因此对视图的更新,系统将自动转0换为对基本表的更新。
- 在对视图的数据进行插入和修改的时候,和向基本表中插入数据一样,用户必须具有向基本表中插入数据的权限。如果视图上没有包括基本表中所有属性为NOT NULL的列,那么插入操作会因为那些列的值为NULL而失败。
- 更新视图的机制
-
- 在一个基本表上建立的视图,只有包含基本表的主键才可以更新;
- 一个视图最多只能有250个列;
- 不能在视图上建立触发器和索引;
- 对视图的一个更新语句只能影响一个基本表,所以由多表连接定义的视
图不允许更新。
-
- 定义视图语句不能使用UNION操作符。
- 视图定义中用到GROUPBY子句或包含集合函数、计算列的数据不能修改。
- 视图的优点
-
- 提供了一定的数据独立性。即使修改了基本表,通过建立视图,也可以不改变应用程序
- 通过视图简化了应用程序和用户查询
- 不同的用户通过视图从不同的观点观察数据
- 视图作为授权的单位提高了系统的安全性
跟踪审查
- 一种事后监视的安全性保护措施,它跟踪数据库的访问活动,以发现数据库的非法访问,达到安全防范的目的。
- MySQL支持的日志
-
- 错误日志,记录MySQL服务器的启动、关闭、运行错误等信息
- 二进制日志,以二进制文件的形式记录数据库中的操作,但不记录查询语句
- 通用查询日志,记录用户登录和记录查询的信息
- 慢查询日志,记录执行时间超过指定时间的操作
- 数据加密存储和传输
-
- 商品化DBMS一般都提供了数据加密例行程序,可根据用户的要求自动对存储和传输的数据进行加密处理。即使未提供这种加密程序,一般也提供了接口,允许用户使用其它厂商推出的加密程序对数据加密。
- 由于数据的加密与解密是比较费时的操作,而且数据加密与解密程序会占用大量系统资源,一般只对高度机密的数据加密。
10.2 数据库的完整性保护
完整性和安全性的关系:它们是数据库保护的两个不同的方面。
- 安全性是防止用户非法使用数据库,包括恶意破坏和越权存取数据,即防范的对象是非法用户和非法操作。
- 完整性则是防止合法用户使用数据库时向数据库中加入不合语义的数据,即防范的对象是不合语义的数据。
DBMS完整性控制应具有的功能:
- 定义功能:为用户提供定义完整性约束条件的命令或工具。
- 检查功能:能够自动检查用户发出的操作请求是否违背了完整性约束条件。
- 保护功能:当发现用户的操作请求使数据违背了完整性约束条件时,能够自动采取一定的措施确保数据的完整性不遭破坏。
完整性约束的分类(根据执行约束的时机分)
- 立即执行的约束:一条语句执行完成后立即检查的完整性约束条件:
- 延迟执行的约束:延迟到整个事务执行结束后,正式提交前进行检查的完整性约束条件;
完整性约束的分类(根据控制的方法分):
- 实体完整性约束:违反实体完整性的操作拒绝执行
- 参照完整性约束:违反参照完整性的操作,一般不是简单地拒绝执行,有时要根据应用语义执行一些附加的操作,以保证数据库的正确性
- 用户定义的完整性约束:违反用户定义的完整性的操作拒绝执行
实现参照完整性控制需要考虑的几个问题
- (1)外键的空值问题。
-
- 允许为空。
-
-
- 例:新生的班级分配,职工的部门分配
-
-
- 不允许为空。
-
-
- 例:学生的选课信息,客户的购货清单
-
- (2)被参照关系中删除元组的问题。
-
- 当删除被参照关系中的某个元组,而参照关系中存在若干元组,其外键值与被参照关系删除元组的主键值相同时,有3种不同的处理策略:
-
-
- 级联删除(Cascades)
- 受限删除(Restricted)
- 置空值删除(Nullifies)
-
- (3)在参照关系中插入元组的问题。
-
- 当在参照关系中插入某个元组,而在被参照关系的元组中不存在与将插入的元组的外键值相同的主键值时,有以下2种策略:
-
-
- 受限插入。(仅当被参照关系中存在与参照关系即将插入的外键值相同的主键值)
- 递归插入
-
- (4)元组中主、外键值的修改问题
-
- 当修改的是被参照关系的主键值,而参照关系中存在与其相等的外键值时,有3种处理策略:
-
-
- 级联修改
- 受限修改
- 置空值修改
-
-
- 当修改的是参照关系的外键值,而其要修改的外键值在被参照关系中不存在这样的主键值时,有2种处理策略:
-
-
- 受限修改
- 递归修改
-
触发器(Triggers)
- 建立(附着)在某个关系(基本表)上的一系列SQL语句的集合(程序),且经预先编译后存储在数据库中。
- 是一种特殊类型的存储过程
- 在用户要对某一表内的数据做增、删、改操作时被触发执行
- 触发器的功能
-
- 实现数据库的完整性保护和安全性保护。
- 触发器的类型
-
- INSERT
- DELETE
- UPDATE
- 触发器的优点
-
- 比由完整性约束条件实现的完整性约束要强的多,且更加灵活。
10.3 数据库的并发控制技术
10.3.1事务
事务的定义
- 用户定义的一组操作序列的集合,数据恢复和并发控制的基本单位。数据库系统在执行事务时,要么执行事务中全部操作,要么一个操作都不执行
事务的特性
- 原子性(Atomicity):一个事务是不可分割的数据库逻辑工作单位,事务中包括的所有操作要么都做,要么都不做。
- 一致性(Consistency):事务执行前后,数据从一个合法性状态变到另一个合法性状态。(语义上的)
- 隔离性(Isolation):一个事务的执行不能被其它事务干扰。
- 持续性(Durability),也称持久性(Permanence):指一个事务一旦提交,它对数据库中数据的改变应该是永久性的,其它操作或故障不对其产生任何影响。(通过事务日志来保证)
事务的应用例子
- 案例描述:用户要购买商品,需要从钱包中取出300元转入商家的钱包中,若从用户钱包中扣除300元后,所剩金额大于0元,则将扣除的300元转入商家的钱包中,否则,取消所有操作,并提示操作失败
- 基本表用户钱包(UserTab)
-
- UserID CHAR(2) PRIMARY KEY,
- UserMoney INT
- 基本表商家钱包(SellerTab)
-
- SellerID CHAR(2),PRIMARY KEY
- SellerMoney INT
- 语法格式
事务的隐式定义
- 系统变量autocommit,默认ON,自动提交
10.3.2 数据库的并发控制
数据库的并发控制以事务为单位进行
- 串行访问:当多个事务对数据库进行操作时,各个事务按顺序执@行,即一个事务执行完全结束后,另一个事务才开始。
- 并发访问:当多个事务对数据库进行操作时,各事务的执行在时间上有重叠。
-
- 交叉并发:在单CPU系统中,多个事务交叉使用CPU。
- 同时并发:在多CPU系统中,多个事务同时占用CPU。

- DBMS对事务采用并发机制的主要目的
-
- 改善系统的资源利用率
- 改善短事务的响应时间
- 但是
-
- 事务的并发控制不当(各事务之间的操作没有做好隔离,互相受到影响),会引起很多严重问题
10.3.3 并发控制不当引起的问题
丢失修改

丢失修改的例子

脏读

脏读的例子

不能重读

不能重读的例子

幻读

幻读的例子

10.3.4 并发控制方法
事务的隔离性级别
- 序列化
-
- 每个用户的事务依次执行,可避免脏读、不可重读和幻读,但性能低下
- 可重复读(默认设置)
-
- 用户在同一个事务中执行同条SELECT语句数次,结果总是相同的,可避免脏读、不可重读,存在幻读问题
- 提交读
-
- 其它事务提交的更新操作,在当前事务中可见,可避免脏读,但存在不可重读和幻读问题
- 未提交读
-
- 无任何隔离(未提交的更新操作也可见),存在所有问题
- 命令
-
- SET [GLOBAL SESSION] TRANSACTION ISOLATION LEVEL <level>
- level
-
- 序列化,SERIALIZABLE
- 可重复读,REPEATABLE READ
- 提交读,READCOMMITTED
- 未提交读,READ UNCOMMITTED
封锁技术
- 封锁的定义
-
- 防止其它事务访问指定资源的一种手段,即在一段时间内禁止某些用户对数据对象做某些操作以避免产生数据的不一致性问题的方法。
- 基本封锁类型(InnoDB)
-
- 1.排它锁(eXclusive locks)又称X锁:如果某事务T对某数据建立了排它锁则该事务能对该数据对象进行读、修改、插入和删除等操作,而其它事务则不能。
- 2.共享锁(Shared locks)又称S锁:如果某事务对某数据建立了共享锁,则该事务能对该数据对象进行读操作,但不能进行修改等更新操作,而其它事务只能对该数据对象加S锁,而不能加X锁,即其它事务只能对该数据对象进行读操作。
- 注意:要使用这两种锁,必须关闭自动提交(autocommit)或者明确开启一个事务。
- 封锁类型的相容矩阵

封锁粒度
- 被封锁数据对象的大小
- 封锁粒度的种类
-
- 行级锁
- 页面锁
- 表级锁
- 封锁粒度与系统并发度和并发控制开销的关系
-
- 封锁粒度越大,系统中能够被封锁的对象就越少,并发度也就越小,当然系统的开销也越少;封锁粒度越小,并发度越高,但系统开销也就越大。
InnoDB的锁设置
- 表级锁
-
- 加锁:LOCK TABLES table_name lock_type,...
- 解锁:UNLOCK TABLES
- 行级锁
-
- 共享锁: SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;
- 排他锁: SELECT* FROM table name WHERE... FOR UPDATE
封锁协议(Lockingprotocol)
- 为保证正确地调度和控制并发操作,所有事务都应遵循的规则集合,是对事务可能执行的方法和基本操作顺序的一种限制。
- 三级封锁协议
-
- 1.一级封锁协议
- 2.二级封锁协议
- 3.三级封锁协议
- 一级封锁协议
-
- 某事务T若要修改某个数据对象,则必须先对该数据对象加X锁,直到事务结束才释放,它可防止"丢失修改"所产生的数据不一致性问题。

- 一级封锁协议的例子

- 二级封锁协议
-
- 一级封锁协议加上某事务T若要读取某个数据对象之前,则必须先对该数据对象加S锁,读完后即可释放S锁,这样可进一步防止"读脏数据"的问题。

- 二级封锁协议的例子

- 三级封锁协议
-
- 一级封锁协议加上某事务T若要读取某个数据对象之前,则必须先对该数据对象加S锁,且直到该事务结束后才释放S锁,这样可进一步防止数据"不可重复读"的问题。

- 一级封锁协议加上某事务T若要读取某个数据对象之前,则必须先对该数据对象加S锁,且直到该事务结束后才释放S锁,这样可进一步防止数据"不可重复读"的问题。
- 三级封锁协议的例子

死锁和活锁
- 活锁
- 避免活锁的简单办法:采用先来先服务的策略。
- 死锁
解决死锁问题的方法
- 预防法
-
- 一次封锁法:规定每个事务必须一次性地将所要访问的数据对象全部加锁,并在操作结束后一次性释放加在所有对象上的锁,这样就能预防死锁的发生
- 顺序封锁法:预先对数据对象规定一个封锁顺序号,所有事务都按照这个顺序对数据对象实施封锁,这样也能预防死锁的发生。
- 诊断解除法
-
- 应用诊断程序发现死锁产生后,通过解锁程序排除死锁。
- 解决死锁的例子


总结

















