数据库系统概论【四】

一、数据库完整性


1、数据库完整性的概念及分类

(1)什么是数据库完整性?

数据库完整性(DB Integrity)是指DBMS应保证的DB的一种特性–在任何情况下的正确性、有效性和一致性

  • 广义完整性:语义完整性、并发控制、安全控制、DB故障恢复等
  • 狭义完整性:专指语义完整性,DBMS通常有专门的完整性管理机制与程序来处理语义完整性问题。(本讲专指语义完整性)

关系模型中有完整性要求:实体完整性、参照完整性、用户自定义完整性

(2)数据库完整性管理的作用

不正当的数据库操作,如输入错误、操作失误、程序处理失误等会引发数据库完整性的问题。数据库完整性管理防止和避免数据库中不合理数据的出现,DBMS应尽可能地自动防止DB中语义不合理现象。如DBMS不能自动防止,则需要应用程序员和用户在进行数据库操作时处处加以小心,每写一条SQL语句都要考虑是否符合语义完整性,这种工作负担是非常沉重的,因此应尽可能多地让DBMS来承担。

(3)怎样保证数据库完整性?

  • DBMS允许用户定义一些完整性约束规则(用SQL-DDL来定义)
  • 当有DB更新操作时,DBMS自动按照完整性约束条件进行检查,以确保更新操作符合语义完整性

DBA使用DBMS提供的DDL编写完整性约束规则,当需要更新程序时,依照完整性规则,检查更新是否符合规则,进而决定是否允许更新。

完整性约束条件(或称完整性约束规则)的一般形式:

Integrity Constraint ::= ( O,P,A,R)

  • O:数据集合:约束的对象?
  • P:谓词条件:什么样的约束?
  • A:触发条件:什么时候检查?
  • R:响应动作:不满足时怎么办?

在A条件下触发对对象O的P约束检查,满足则更新,不满足启动相应动作R

(4)数据库完整性的分类

①按约束对象分类

  • 域完整性约束条件:施加于某一列上,对给定列上所要更新的某一候选值是否可以接受进行约束条件判断,这是孤立进行的
  • 关系完整性约束条件:施加于关系/table上,对给定table上所要更新的某一候选元组是否可以接受进行约束条件判断,或是对一个关系中的若干元组和另一个关系中的若干元组间的联系是否可以接受进行约束条件判断

前者为域完整性约束条件后者为关系完整性约束条件

②按约束来源分类

  • 结构约束:来自于模型的约束,例如函数依赖约束、主键约束(实体完整性)、外键约束(参照完整性),只关心数值相等与否、是否允许空值等;

  • 内容约束:来自于用户的约束,如用户自定义完整性,关心元组或属性的取值范围。例如Student表的Sage属性值在15岁至40岁之间等。

蓝色为结构约束,红色为内容约束

③按约束状态分类

  • 静态约束:要求DB在任一时候均应满足的约束;例如Sage在任何时候都应满足大于0而小于150(假定人活最大年龄是150)。
  • 动态约束:要求DB从一状态变为另一状态时应满足的约束;例如工资只能升,不能降:工资可以是800元,也可以是1000元;可以从800元更改为1000元,但不能从1000元更改为800元。

2、SQL语言实现约束的方法-Create Table

CreateTable有三种功能:定义关系模式、定义完整性约束和定义物理存储特性这里体现了定义完整性约束

1586405208985

  • DEFAULT { default_constant | NULL}指的是设置默认值
  • col_constr为列约束,之后介绍
  • table_constr为表约束,之后介绍

(1)Col_constr列约束

Col_constr列约束:只能应用在单一列上,其后面的约束如UNIQUE,PRIMARY KEY及search_cond只能是单一列唯一、单一列为主键、和单一列相关

  • 使用REFERENCES引用另一表tablename的列colname的值,如有ON DELETE CASCADE 或ON DELETE SETNULL语句,则删除被引用表的某列值v 时,要将本表该列值为v 的记录删除或列值更新为null;缺省为无操作 。
  • CHECK后的条件可以是任意where语句
  • 定义REFERENCES,不需要指出FOREIGN KEY,默认就是本列作为外键,只需要指出外表的对应主键
  • 最后还可以使用on update和ondelete同理。默认是no action不作为,可以选择 cascade级联操作和set null

示例

//假定Ssex只能取{男,女}, 1≤Sage≤150, D#是外键

1
2
3
4
5
Create Table Student ( S# char(8) not null unique, Sname char(10),
Ssex char(2) constraint ctssex check (Ssex=‘男’ or
Ssex=‘女’), Sage integer check (Sage>=1 and Sage<150),
D# char(2) references Dept(D#) on delete cascade,
Sclass char(6) );

//假定每门课学分最多5分,最少0分

1
2
3
4
Create Table Course ( C# char(3) , Cname char(12), Chours integer,
Credit float(1) constraint ctcredit check (Credit >=0.0 and
Credit<=5.0 ), T# char(3) references Teacher(T#) on delete
cascade );

(2)table_constr表约束

table_constr表约束:是应用在关系上,即对关系的多列或元组进行约束,列约束是其特例

  • 列约束直接跟随在列后,表约束需要逗号隔开后书写,虽然逗号隔开区分其和其他的表述,可以在任意位置书写,但是我们一般放在句末
  • 列约束直接跟在列后,所以定义REFERENCES,不需要指出FOREIGN KEY,默认就是本列作为外键,只需要指出外表的对应主键即可。而表约束则需要指出来本表作为外键的列
  • Check只涉及一个列,则列约束和表约束效果相同,若涉及多个列则约束效果不同

例如:

//假定严格约束20学时一个学分

1
2
3
4
5
Create Table Course ( C# char(3) , Cname char(12), Chours integer,
Credit float(1) constraint ctcredit check (Credit >=0.0 and
Credit<=5.0 ), T# char(3) references Teacher(T#) on delete
cascade, primary key(C#),
constraint ctcc check(Chours/Credit = 20) );
1
2
3
4
Create Table SC ( S# char(8) check( S# in (select S# from student)) ,
C# char(3) check( C# in (select C# from course)) ,
Score float(1) constraint ctscore check (Score>=0.0 and
Score<=100.0),

(3)撤消或追加约束的语句 Alter Table(不同系统可能有差异)

  • drop:删除
  • modify:修改
  • add:添加

示例:撤消SC表的ctscore约束(由此可见,未命名的约束是不能撤消)

1
2
Alter Table SC
DROP CONSTRAINT ctscore;

示例:若要再对SC表的score进行约束,比如分数在0~150之间,则可新增加一个约束。在Oracle中增加新约束,需要通过修改列的定义来完成

1
2
3
Alter Table SC
Modify ( Score float(1) constraint nctscore check (Score>=0.0 and
Score<=150.0) );

有些DBMS支持独立的追加约束,注意书写格式可能有些差异

1
2
Alter Table SC
Add Constraint nctscore check (Score>=0.0 and Score<=150.0) );

3、SQL语言实现约束的方法-断言

一个断言就是一个谓词表达式,它表达了希望数据库总能满足的条件,表约束和列约束就是一些特殊的断言SQL还提供了复杂条件表达的断言。其语法形式为:

1
CREATE ASSERTION <assertion-name> CHECK <predicate>

当一个断言创建后,系统将检测其有效性,并在每一次更新中测试更新是否违反该断言

断言测试增加了数据库维护的负担,要小心使用复杂的断言。

示例

“每笔贷款,要求至少一位借款者账户中存有最低数目的余额,例如1000元”

1
2
3
4
borrower(customer_name, loan_number,…) //客户及其贷款(一笔贷款的借款者)
account(account_number,…, balance) //账户及其余额
depositor(account_number, customer_name) //客户及其账户(一个借款者的账户)
loan(loan_number, amount) //每一笔贷款
1
2
3
4
5
6
7
8
9
create assertion balance_constraint check
(not exists (
select * from loan
where not exists (
select * from borrower, depositor, account
where loan.loan_number = borrower.loan_number
and borrower.customer_name = depositor.customer_name
and depositor.account_number = account.account_number
and account.balance >= 1000)))

4、实现数据库动态完整的方法—触发器Trigger

Create Table中的表约束和列约束基本上都是静态的约束,也基本上都是对单一列或单一元组的约束(尽管有参照完整性),为实现动态约束以及多个元组之间的完整性约束,就需要触发器技术Trigger

Trigger是一种过程完整性约束(相比之下,Create Table中定义的都是非过程性约束),是一段程序该程序可以在特定的时刻被自动触发执行比如在一次更新操作之前执行,或在更新操作之后执行

  • 事件:BEFORE | AFTER { INSERT | DELETE | UPDATE …}当一个事件(Insert, Delete, 或Update)发生之前Before或发生之后After触发。操作发生,执行触发器操作需处理两组值:更新前的值和更新后的
    值,这两个值由corr_name_def的使用来区分

    • 提交时刻为,提交SQL语句,BEFORE和AFTER时刻的区别瞬间就是值更新与否的瞬间
  • [FOR EACH ROW | FOR EACH STATEMENT]对操作影响的每一条结果(前者)进行后续操作次数和操作影响的行数相同,或整个更新操作完成(后者)进行后续操作只进行一次

  • corr_name_def的定义

    • NEW [row] [as] new_row_corr_name//更新后的新元组命别名为
    • OLD [row] [as] old_row_corr_name//更新前的旧元组命别名为
    • NEW TABLE [as] new_table_corr_name//更新后的新Table命别名为
    • OLD TABLE [as] old_table_corr_name//更新前的旧Table命别名为
  • corr_name_def将在检测条件或后面的动作程序段中被引用处理

实例:

设计一个触发器当进行Teacher表更新元组时, 使其工资只能升不能降

1
2
3
4
5
6
7
8
create trigger teacher_chgsal before update of salary
on teacher
referencing new x, old y
for each row when (x.salary < y.salary)
begin
raise_application_error(-20003, 'invalid salary on update');
//此条语句为Oracle的错误处理函数
end;

假设student(S#, Sname, SumCourse), SumCourse为该同学已学习课程的门数,初始值为0,以后每选修一门都要对其增1 。设计一个触发器自动完成上述功能。

1
2
3
4
5
6
7
create trigger sumc after insert on sc
referencing new row newi
for each row//这里任何时候都为真。
begin
update student set SumCourse = SumCourse + 1
where S# = newi.S# ;
end;

假设student(S#, Sname, Sage, Ssex, Sclass)中某一学生要变更其主码S#的值,如使其原来的98030101变更为99030131, 此时sc表中该同学已选课记录的S#也需自动随其改变。设计一个触发器完成上述功能

1
2
3
4
5
6
create trigger updS# after update of S# on student
referencing old oldi, new newi
for each row//这里任何时候都为真。
begin
update sc set S# = newi.S# where S# = :oldi.S# ;
end;

假设student(S#, Sname, SumCourse), 当删除某一同学S#时,该同学的所有选课也都要删除。设计一个触发器完成上述功能

1
2
3
4
5
6
create trigger delS# after delete on Student
referencing old oldi
for each row
begin
delete sc where S# = :oldi.S# ;
end;

假设student(S#, Sname, SumCourse), 当删除某一同学S#时,该同学的所有选课中的S#都要置为空值。设计一个触发器完成上述功能

1
2
3
4
5
6
create trigger delS# after delete on Student
referencing old oldi
for each row
begin
update sc set S# = Null where S# = :oldi.S# ;
end;

假设Dept(D#, Dname, Dean), 而Dean一定是该系教师Teacher(T#, Tname, D#, Salary)中工资最高的教师。设计一个触发器完成上述功能(更新系主任了)

1
2
3
4
5
6
7
8
9
create trigger upddean before update of Dean on Dept
referencing old oldi, new newi
for each row when ( dean not in
(select Tname from Teacher where D# = :newi.D#
and salary >=
all (select salary from Teacher where D# = :newi.D#))
begin
raise_application_error(-20003, 'invalid Dean on update');
end;

二、数据库安全性


1、数据库安全性的概念

数据库安全性是指DBMS应该保证的数据库的一种特性(机制或手段):免受非法、非授权用户的使用、泄漏、更改或破坏

数据库安全性管理涉及许多方面:

  • 社会法律及伦理方面:私人信息受到保护,未授权人员访问私人信息会违法

  • 公共政策/制度方面:例如,政府或组织的信息公开或非公开制度

  • 安全策略:政府、企业或组织所实施的安全性策略,如集中管理和分散管理,需者方知策略(也称最少特权策略)

  • 数据的安全级别: 绝密(Top Secret), 机密(Secret),可信(Confidential)和无分类(Unclassified)

  • 数据库系统DBS的安全级别:物理控制、网络控制、操作系统控制、DBMS控制

数据库安全是由各个层次来保障的,物理实现、网络控制、操作系统、DBMS控制等等一些列的层次和方向实现,这里我们只着重介绍DBMS控制方面

(1)DBMS的安全机制

  • 自主安全性机制:存取控制(AccessControl)通过权限在用户之间的传递,使用户自主管理数据库安全性

  • 强制安全性机制:通过对数据和用户强制分类,使得不同类别用户能够访问不同类别的数据

  • 推断控制机制:(可参阅相关文献)

    • 防止通过历史信息,推断出不该被其知道的信息;
    • 防止通过公开信息(通常是一些聚集信息)推断出私密信息(个体信息),通常在一些由个体数据构成的公共数据库中此问题尤为重要
  • 数据加密存储机制:(可参阅相关文献)

    • 通过加密、解密保护数据,密钥、加密/解密方法与传输

本课程着重介绍DBMS的自主安全性机制和强制安全性机制

(2)数据库管理员的责任和义务

  • 熟悉相关的法规、政策,协助组织的决策者制定好相关的安全策略
  • 规划好安全控制保障措施,例如,系统安全级别、不同级别上的安全控制措施,对安全遭破坏的响应,
  • 划分好数据的安全级别以及用户的安全级别
  • 实施安全性控制:DBMS专门提供一个DBA账户,该账户是一个超级用户或称系统用户。DBA利用该账户的特权可以进行用户账户的创建以及权限授予和撤消、安全级别控制调整等

2、数据库自主安全性机制

通常情况下,自主安全性是通过授权机制来实现的。用户在使用数据库前必须由DBA处获得一个账户,并由DBA授予该账户一定的权限,该账户的用户依据其所拥有的权限对数据库进行操作; 同时,该帐户用户也可将其所拥有的权利转授给其他的用户(账户),由此实现权限在用户之间的传播和控制。

(1)DBMS怎样自动实现自主安全性?

DBMS允许用户定义一些安全性控制规则(用SQL-DCL来定义),当有DB访问操作时,DBMS自动按照安全性控制规则进行检查,检查通过
则允许访问,不通过则不允许访问

(2)数据库自主安全性访问规则

  • { AccessRule}通常存放在数据字典或称系统目录中,构成了所有用户对DB的访问权利;
  • 用户多时,可以按用户组建立访问规则
  • 访问对象可大可小(目标粒度Object granularity):属性/字段、记录/元组、关系、数据库
  • 权利:包括创建、增、删、改、查等
  • 谓词:拥有权利需满足的条件

(3)一个自主安全性控制的例子

员工管理数据库的安全性控制示例

Employee(P#, Pname, Page, Psex, Psalary, D#, HEAD)

安全性访问要求:

  • 员工管理人员:能访问该数据库的所有内容,便于维护员工信息
  • 收发人员:访问该数据库以确认某员工是哪一个部门的,便于收发工作,只能访问基本信息,其他信息不允许其访问
  • 每个员工:允许其访问关于自己的记录,以便查询自己的工资情况,但不能修改
  • 部门领导:能够查询其所领导部门人员的所有情况
  • 高层领导:能访问该数据库的所有内容,但只能读

自主安全性的实现方式

①存储矩阵

通过S和O能够确定一个t,存储矩阵能够实现SOT的安全性控制但是无P的参与。

可以编写一个程序,在用户提交了一个SQL语句的时候,先根据表对象在存储矩阵中查询访问关系,若全都能访问则再在存储矩阵中查询表的属性的访问关系若全都能访问则能够执行,否则不能。而这个程序就是DBMS的安全性控制程序

②视图

通过视图可以限制用户对关系中某些数据项的存取,例如:

1
2
视图1:CreateEmpV1as select*fromEmployee
视图2CreateEmpV2as selectPname,D#fromEmployee

通过视图可将数据访问对象与谓词结合起来,限制用户对关系中某些元组的存取,例如:

1
2
视图1: CreateEmpV3asselect*fromEmployeewhereP#=:UserId
视图2CreateEmpV4asselect*fromEmployeewhere Head=:UserId

用户定义视图后,视图便成为一新的数据对象,参与到存储矩阵与能力表中进行描述,所以他可以递归使用,视图中再建立新的视图。

视图全部实现了SOTP的控制

3、利用SQL语言实现数据库自主安全性

SQL语言包含了DDL,DML和DCL。数据库安全性控制是属于DCL范畴

  • (级别1)Select : 读(读DB, Table, Record, Attribute, … )
  • (级别2)Modify : 更新
    • Insert : 插入(插入新元组, … )
    • Update : 更新(更新元组中的某些值, …)
    • Delete : 删除(删除元组, …)
  • (级别3)Create : 创建(创建表空间、模式、表、索引、视图等)
    • Create : 创建
    • Alter : 更新
    • Drop : 删除

级别高的权利自动包含级别低的权利。如某人拥有更新的权利,它也自动拥有读的权利。在有些DBMS中,将级别3的权利称为账户级别的权利,而将级别1和2称为关系级别的权利。

(1)授权命令

  • user-id ,某一个用户账户,由DBA创建的合法账户

  • public, 允许所有有效用户使用授予的权利

  • privilege是下面的权利

    • SELECT | INSERT | UPDATE | DELETE | ALL PRIVILEDGES
  • WITH GRANT OPTION选项是允许被授权者传播这些权利,添加则允许,不添加则不允许

示例

假定高级领导为Emp0001, 部门领导为Emp0021, 员工管理员为Emp2001,收发员为Emp5001(均为UserId, 也即员工的P#)

1
2
3
4
Grant All Priviledges ON Employee TO Emp2001;
Grant SELECT ON EmpV2 TO Emp5001 ;
Grant SELECT ON EmpV3 TO public;
Grant SELECT ON EmpV4 TO Emp0021;

注意:授予视图访问的权利,并不意味着授予基本表访问的权利(两个级别:基本关系级别和视图级别)

授权者授予的权利必须是授权者已经拥有的权利

(2)收回授权命令

示例

1
revoke select on employee from UserB;

4、安全型控制的其他简介

(1)授权的传播范围问题

  • 传播范围包括两个方面:水平传播数量和垂直传播数量

    • 水平传播数量是授权者的再授权用户数目(树的广度)
    • 垂直传播数量是授权者传播给被授权者,再被传播给另一个被授权 者, …传播的深度(树的深度)
  • 有些系统提供了传播范围控制,有些系统并没有提供,SQL标准中也并没有限制。

  • 当一个用户的权利被收回时,通过其传播给其他用户的权利也将被收回

  • 如果一个用户从多个用户处获得了授权,则当其中某一个用户收回授权时 ,该用户可能仍保有权利。例如UserC从UserB和UserE处获得了授权,当 UserB收回时,其还将保持UserE赋予其的权利。

由此引发的授权范围问题值得思考,这里不再深入,可查阅资料

(2)强制安全性机制

强制安全性通过对数据对象进行安全性分级:绝密(Top Secret), 机密(Secret),可信(Confidential)和无分类(Unclassified),同时对用户也进行上述的安全性分级从而强制实现不同级别用户访问不同级别数据的一种机制.

  • 用户S, 不能读取数据对象O, 除非Level(S)>=Level(O)
    • 低阶用户不能读取高阶数据
  • 用户S, 不能写数据对象, 除非Level(S)<=Level(O)。
    • 高阶用户不能写低阶数据,否则更改了对象的安全等级使得原本能访问的低阶用户也不能访问了

DBMS引入强制安全性机制, 可以通过扩展关系模式来实现,对属性和元组引入安全性分级特性或称分类特性

R(A1: D1, C1, A2: D2, C2…, An:Dn, Cn, TC)其中 C1,C2,…,Cn分别为属性D1,D2,…,Dn的安全分类特性; TC为元组的分类特性这样, 关系中的每个元组, 都将扩展为带有安全分级的元组, 例如

强制安全性机制使得关系形成为多级关系(不同级别用户所能看到的关系的子集),也出现多重实例、多级关系完整性等许多新的问题或新的处理技巧,在使用中需注意仔细研究。关于强制安全性机制的内容,可参看其他有关的文献。

4、数据库安全性控制的常用方法

1.安全性标准:TCSEC和CC(我国标准)

2.存取控制:存钱控制的机制主要包括定义用户权限和合法权限检查

3.自主存取控制(C2级):

用户对于不同的数据库对象有不同的存取权限,不同的用户对同一对象也有不同的权限,用户还可以将其拥有的权限授予其他人

用户权限由两个要素组成:数据库对象和操作类型,在数据库系统中,定义存取权限被称为授权

sql语句:([]表示可有可无)

授权:

GRANT<权限>[,<权限>]…

ON<对象类型><对象名>[,<对象类型><对象名>]…

TO<用户>[,<用户>]…

[WITH GRANT OPTION];

回收权限:

REVOKE<权限>[,<权限>]…

ON<对象类型><对象名>[,<对象类型><对象名>]…

FROM<用户>[,<用户>]…[CASCADE|RESTRICT];

角色:

CREATE RPLE <角色名>

给角色授权和收回与普通的操作一致,将权限替换成角色

4.强制存取控制(B1级):

每一个数据库对象被标以一定的密级,每一个用户也被授予某一个级别的许可证。对于任意一个对象,只有具有合法许可证的用户才可以存取

基本规则:

1.仅当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体

2.仅当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体

例子:银行职业可以修改金额但是不可以看金额,主管可以看数据但是不可以改数据。

5.视图:可以通过视图机制将要保密的数据对无权存取的用户隐藏起来,从而自动对数据提供一定程度的安全保护

SQL:

CREATE VIEW XXX

AS

SELECT NAME

FROM YYY

6.审计:把用户对数据库的所有操作自动记录下来放入审计日志。提供了一种事后检查的安全机制

7.数据加密:存储加密和传输加密

-----------------------本文结束 感谢阅读-----------------------
坚持原创技术分享,您的支持将鼓励我继续创作!恰饭^.^~