目录java
第一章、引言mysql
1.1 文件管理系统坏处linux
1.2 数据视图算法
1.3 数据模型sql
1.4 数据库语言数据库
2.3 码安全
sql是数据库查询语言。有如下几个部分:
char和char比较时,长度不一样追加空格 。char和varchar比较可能返true、false。建议使用varchar而不是char来解决问题。
mysql> create table d( -> good varchar(20), -> g varchar(20) not null, -> primary key(good,g) -> ); create table b( course_id varchar(20), tot_cred numeric(3,0) default 0, foreign key(course_id) references d );
insert into wang values("L",15,69); insert intp wang(a,b,c) values("L",15,69); //推荐 mysql> insert into list(id) -> select id -> from consumer;
delete from wang where name='Liu'; drop table wang; alter table user add good varchar(20); alter table user drop good;
mysql> update list -> set days=1 -> where days=2;
mysql> update student S -> set tot_cred=( -> select case when sum(credits) is not null then sum(credits) else 0 end -> from takes natural join course -> where S.ID=takes.ID and -> takes.grade<>'F' and takes.grade is not null);
select distinct id from list; select all id from list;
mysql> select no*2 from list -> where no>1000 and days<>1;
select name,course_id from instructor,teachers where instructor.ID=teaches.ID
mysql> select * -> from consumer natural join list; mysql> select * -> from consumer join list using(id) -> ;
mysql> select T.sex as bala -> from consumer as c,consumer as t -> where c.sex=t.sex and t.name='王文萱'; mysql> select * from list where id like '211%'; mysql> select * from list -> order by id desc,no asc; mysql> select * from list -> where no not between 1000 and 1001; mysql> select * from instructor,teaches -> where (instructor.ID,dept_name)=(teaches.ID,'Biology');
所有自动去重,后面加上all不去重。
mysql> select * from list -> where no is unknown; mysql> select * from list -> where no is null;
mysql> mysql> select distinct course_id -> from section -> where semester='Fall' and year='2009' -> and course_id in(select distinct course_id -> from section -> where semester='Spring' and year=2010); mysql> select distinct name -> from instructor -> where name not in('Wang','Wen'); mysql> mysql> select count(distinct ID) -> from takes -> where (course_id,sec_id,semester,year)in(select course_id,sec_id,semester,year -> from teaches -> where teaches.ID=10101);
mysql> select name -> from instructor -> where salary>some(select salary -> from instructor -> where dept_name='Biology') -> ; mysql> select dept_name -> from instructor -> group by dept_name -> having avg(salary)>all( -> select avg(salary) -> from instructor -> group by dept_name);
select name from student where not exists( ( select course_id from course where dept_name='Biology' ) except ( select T.course_id from takes as T where S.ID=T.ID ) );
select T.course_id from course as T where unique(select R.course_id from section as R where T.course_id=R.course_id and R.year=2009);
select dept_name from (select dept_name,avg(salary) as avg_salary from instructor group by dept_name) as dept_avg(dept_name,avg_salary) where avg_salary>42000; select dept_name from (select dept_name,avg(salary) as avg_salary from instructor group by dept_name) where avg_salary>42000; select name from instructor I1,lateral (select avg(salary) as avg_salary from instructor I2 where I2.dept_name=I1.dept_name); with dept_total(dept_name,value) as (select sept_name,sum(salary) from instructor group by dept_name), dept_total_avg(value) as (select avg(value) from dept_total) select dept_name from dept_total,dept_total_avg where dept_total.val>=dept_total_avg.value;
show create table XXX
左外链接(left join) | 只保留出如今左链接以前的关系中的元组 |
右外链接(right join) | 只保留出如今右外链接以后的关系中的元组 |
全外链接(full join) | 保留出如今两个关系中的元组 |
咱们能够按照以下方式计算左外链接运算:
首先,像前面那样计算出内链接的结果;而后,对于在内链接的左侧关系中任意一个与右侧关系中任何元组都不匹配的元组t,向链接结果中加入一个元组r,r的构造以下:
- 元组r从左侧关系获得的属性为t中的值
- r的其它属性被设为空值
链接类型 | 链接条件 |
inner join、left outer join、right outer join、full outer join | natural、on、using |
mysql> select * -> from consumer join list on consumer.id=list.id; mysql> select * -> from(select * -> from list) -> natural full outer join -> (select * -> from consumer);
mysql> create view f as -> select * from list; Query OK, 0 rows affected (0.13 sec) mysql> create view w(id) as -> select id from list; Query OK, 0 rows affected (0.05 sec) mysql> select * from w; mysql> select * from f; mysql> create view g as -> select * -> from list -> where no<2000 -> with check option; Query OK, 0 rows affected (0.08 sec) mysql> insert into g(id,no) values('211022199906030548',5000); ERROR 1369 (HY000): CHECK OPTION failed 'haha.g'
特定数据库系统容许存储视图关系,可是它们保证:若是用于定义视图的实际关系改变,视图也跟着修改。这样的视图成为物化视图
保护物化视图一直在更新状态的过程称为物化视图维护,或者简称视图维护
那些须要快速响应基大于关系上汇集运算的特定查询也会从建立和查询对应物化视图受益良多。
物化视图带来的好处还须要和存储代价和增长的更新开销相权衡。
若是定义视图的查询对下列条件知足,咱们称视图是可更新的:
- from 子句中只有一个数据库关系
- select 子句中只包括关系的属性名,不包含任何表达式、汇集和distinct声明
- 任何没有出如今select子句中的属性能够取空值;即这些属性上没有not null约束,也不构成主码的一部分。
- 查询中不含有group by 和having子句
SQL规定当一条SQL语句被执行,就隐式的开始了一个事务
下列SQL语句会结束一个事务
commit work:提交当前事务,也就是将该事物所作的更新在数据库中持久保存。在事物被提交后,一个新的事物自动开始
rollback work:回滚当前事务,也就是撤销该事务中全部SQL语句对数据库的更新,就恢复到执行该事务第一语句以前的状态。
关键词work可选
一个事务或者在完成全部步骤后提交其行为,或者在不能成功完成其全部动做的状况下回滚其全部动做,经过这种方式数据库提供了对事务具备原子性的抽象,原子性即不可分割性。
要么全部事务的全部影响被反映到数据库中,要么任何影响都没有(在回滚以后)
容许将全部SQL语句加载begin atomic……end之间。关键字之间的语句构成了单一事务。
mysql> start transaction; Query OK, 0 rows affected (0.08 sec) mysql> insert into exam values(2); Query OK, 1 row affected (0.03 sec) mysql> rollback; Query OK, 0 rows affected (0.06 sec) mysql> select * from exam; +------+ | id | +------+ | 1 | +------+ mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> update exam set id=2 where id=1; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.06 sec) mysql> select * from exam; +------+ | id | +------+ | 2 | +------+ 1 row in set (0.00 sec)
references能够显示指定被参照关系的属性列表,然而这个指定的属性列表必须声明为被参照关系的候选码。当违反参照完整性约束时,一般是拒绝执行致使完整性破坏的操做(即进行更新操做的事务被回滚)
on delete cascade ,若删除department中的元组致使了此参照完整性约束被违反,则删除并不被系统拒绝,而是对course关系做级联删除
事务中对完整性约束的违反,SQL容许将initially deffrred子句加入到约束声明中,这样完整性约束不是在事务的中间步骤上检查,而是在事务结束的时候检查。默认状况下它会被当即检查
复杂check条件检测开销很大,咱们可使用断言,表达数据库总能知足某一个条件
mysql> alter table example change id id varchar(10) primary key; mysql> alter table example add id varchar(20) primary key; ERROR 1060 (42S21): Duplicate column name 'id' mysql> create table x( -> id varchar(20, -> check(id in ('Fall','Winter')); mysql> create table wang( -> id varchar(20) -> check(id in(select id from list)) -> ); mysql> create table e( -> id int, -> unique(id)); mysql> create table wang( -> id varchar(20), -> foreign key(id) references list -> on delete cascade); mysql> create assertion a check -> (not exists(select * -> from list -> where no>9000) -> );
一些获取当前日期和时间的函数
current_date返回当前日期
current_time返回当前时间
localtime返回当前的本地时间
时间戳(日期加上时间)由current_timestamp(带有时区)
localtimestamp(本地日期和时间,不带时区)
SQL容许在上面列出的全部类型上进行比较运算,也容许在各类数字类型上进行算术运算和比较运算
还支持interval数据类型,容许在日期、时间、和时间间隔上进行运算
x,y都是date类型,那x-y就是时间间隔类型,其值为日期x到日期y间隔的天数
mysql> select current_date - date'2001-05-24'; mysql> select current_date; mysql> select date'2001-04-25',time'09:30:00',timestamp'2001-04-25 09:30:00'; //从date中提取域。有year,month,day,hour,minute,second mysql> select extract(year from date'2001-05-24'); mysql> cast('2001-05-24' as DATE); //将字符串转化称DATE
mysql> create index i on wang(id);
mysql> create table wen( -> a clob(10KB), -> b blob (10MB));
mysql> create type Dollars as numeric(12,2); mysql> create type Dollar as numeric(12,2); create table department( budget Dollars ); //若是不转换的话,Dollars=Dollar会报错 cast(department.Dollars to numeric(12,2);
域和类型的差异:
1.在域上,能够声明约束,也能够为域类型变量定义默认或默认值
2.域不是强类型,一种域类型的值能够被赋给另外一种域类型的变量,只要他们基本类型相同
把check子句用到域上,被声明为来自该域的任何变量都必须知足这个谓词
constraint salary_value_test子句可选,用来将该约束命名为salary_value_test
create domain DDollaers as numeric(12,2) not null; create domain YearlySalary numeric(8,2) constrait salary check(value>=29000);
create table 的扩展
建立与现有的表模式相同的表
把查询的结果存储成一个新表
一条用于建立表,另外一条用于把查询结果插入到表中
create table...as与create view语句很是类似
区别在于当表被建立时表的内容被加载,但视图老是反应当前查询的结果
模式,目录和环境
当代数据库系统提供了三层结构的关系命名机制。最顶层由目录构成,每一个目录能够包含模式。诸如关系、视图都包含在模式中
create schema和drop schema来建立和删除模式。
权限包括select、insert、update、delete
all privileges全部权限能够用做全部权限的简写形式
一个建立了新关系的用户将自动被授予该关系上的全部权限
展现当前用户权限
show grants;
grant用来授予权限
update能够在关系的全部属性上授予,也能够只在某些属性上授予
insert也能够指定属性列表,系统将其余属性要么赋予默认值要么赋值为null
用户名public指系统的全部当前用户和未来用户
默认状况下,被授予权限的用户和角色无权把此权限授予其余用户/角色
SQL容许用授予权限的接受者能够进一步把权限授予其余人
不容许对一个关系的指定元组受权
远程链接时:
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON 你的数据库.* TO '用户名'@'%' identified by '密码'
使用revoke语句来收回权限
grant select on department to Amith; grant update(no) on department tomith; grant select on department to public; revoke select on department to Amith; revoke update(no) on department tomith; revoke select on department to public;
角色
在数据库中创建一个角色集,能够给角色授予权限,就和给每个用户受权的方式彻底同样
建立角色
受权给角色
角色能够受权给用户,也能够受权给其余角色
一个用户或一个角色的权限包括:
create role instructor; grant select on takes to instructor; grant dean to Amith; create role dean; grant indtructor to dean; grant dean to Satoshi;
视图的受权。在这个例子中,视图的建立者必须在instructor关系上具备select权限,不然系统会拒绝这样的视图建立请求
create view geo_instructor as ( select * from instructor );
模式的受权
只有模式的拥有则才能执行对模式的修改。
//容许Amith建立参照department的dept_name的关系 grant references (dept_name) on department to Amith;
权限的转移,容许权限的接受者将该权限授予给其余用户
grant select on department to Amith with grant option;
权限的收回
revoke select on department to Amith restrict; revoke select on department to Amith cascade; set role me; granted by current_role;
restrict防止权限的级联收回
替换成cascade表示须要级联收回,默认须要级联收回。
授予权限时将受权人设置为一个会话所关联的当前角色,而且当角色不为空时,可在受权语句后加
收回角色/权限时任然能保持当前角色
关系代数、元组关系演算、域关系演算
关系代数基本运算:选择、投影、并、集合差、笛卡尔积、改名
选择运算,一元运算
选出知足给定谓词的元组,用sigma(σ)来表示,将谓词写做σ的下表
例如:属于物理系的元组能够这样写
一般,咱们容许在选择谓词中进行比较,使用的是=、≠、<、≤、>、≥
另外,咱们能够用连词将多个谓词合并为一个较大的谓词。
例如:
投影运算
投影运算是一元运算,它返回做为参数的关系,但把某些属性排除在外。重复行去除
例如:
关系运算的组合
例如:找出物理系的全部教师的名字
并运算
就是将两个集合并起来。去重
例如:找出开设在2009年秋季学期或者2010年春季学期或者这二者皆开的全部课程的集合
另外一方面,设r和s是数据库关系或者做为关系代数表达式结果的临时关系。要使r U s有意义,需知足如下两个条件:
(1)关系r和s必须是同元的,即它们的属性数目必须相同
(2)对全部的i,r的第i个属性的域必须和s的第i个属性的域相同
集合差运算
用 - 表示集合差运算,能够找出在一个关系中而不在另外一个关系中的那些元组。
例如:找出全部开设在2009年秋季学期可是在2010年春季学期不开的课程
另外一方面,设r和s是数据库关系或者做为关系代数表达式结果的临时关系。要使r - s有意义,需知足如下两个条件:
(1)关系r和s必须是同元的,即它们的属性数目必须相同
(2)对全部的i,r的第i个属性的域必须和s的第i个属性的域相同
笛卡尔积运算
用X表示笛卡尔积,能够将任意两个关系的信息组合在一块儿。
改名运算
关系代数表达式的结果没有可供咱们引用的名字,咱们能够经过小写希腊字母rho(ρ)表示的改名运算来完成这一任务。
返回表达式E的结果,并把名字x赋给了它
返回表达式E的结果,并赋给它名字x,同时将各属性改名为A1,A2,... ,An
关系代数中基本的表达式是以下两者之一:
若E1,E2是关系代数表达式,则一下这些都是关系代数表达式:
集合交运算
例如:在2009年秋季和2010年春季都开设的课程
集合交运算与集合差运算的关系:
天然链接运算
用链接符号来表示
天然链接运算首先造成它的两个参数的笛卡尔积,而后基于两个关系模式中都出现的属性上的相等性进行选择,最后还要去除重复属性。
例如:找出全部教师的姓名,连同他们教的全部课程的course_id
天然链接是可结合的
theta链接是天然链接的扩展,它使得咱们能够把一个选择运算和一个笛卡尔积运算合并为单独的一个运算,即天然链接是选出笛卡尔积中相同的属性,而theta链接是选出笛卡尔积中知足该选择运算的属性。
赋值运算
将R x S的结果赋给temp1
外链接运算
外链接是链接运算的扩展,能够处理确实的信息。有左外链接、右外链接和全外链接
左外链接():取出左侧关系中全部与右侧关系的任一元组都不匹配的元组,用空值填充全部来自右侧关系的属性,再把产生的元组加到天然链接的结果中。
右外链接():与左外链接相对称
全外链接():既作左外链接又作右外链接,既填充左侧关系中与右侧关系的任一元组都不匹配的元组,又填充右侧关系中与左侧关系的任一元组都不匹配的元组,并把结果都加到链接的结果中。
广义投影
广义投影容许在投影列表中使用算术运算和字符串函数等来对投影进行扩展。
例如:
汇集
汇集运算能够用来对值的集合使用汇集函数,例如计算最小值或者求平均值
汇集函数:输入值的一个聚集,将单一值做为结果返回。好比输入几个数的集合,返回他们的和做为结果
将distinct添加在函数名后,能够去除重复
例如:
元组关系演算
元组关系演算表达式具备以下形式:
其中P是一个公式,公示中能够出现多个元组变量。若是元组不被“存在”或“任意”修饰,则称为自由变量。
域关系演算
域关系演算是从属性域中取值的域变量,而不是整个元组的值。
概念设计:E-R图建立
逻辑设计:E-R模型映射到关系模式
物理设计。
设计一个数据库模式的时候,必须避免的两个主要的缺陷
(1)冗余:一个很差的设计可能会重复信息。信息的冗余表达的最大问题是当对一条信息进行更新,但没有将这条信息的全部拷贝都更新时这条信息的拷贝会变得不一致。
(2)不完整:如字面意思,一个很差的设计可能会使得企事业机构的某些方面难于甚至没法建模。
实体-联系(E-R)数据模型的提出旨在方便数据库的设计,它是经过容许定义表明数据库全局逻辑结构的企业模式实现的。
实体:是现实世界中可区别于全部其余对象的一个“事物”或“对象”。
实体集:是相同类型即具备相同性质(或属性)的一个实体集合。例如一所给定大学的全部教师的集合可定义为实体集instructor。实体集没必要互不相交
实体集的外延:属于实体集的实体的实际集合
联系:是指多个实体间的相互关联,也能够具备描述性属性
联系集:是相同类型联系的集合。
参与:实体集之间的关联称为参与。也就是说,实体集E1,E2,...,En参与联系集R
角色:实体在联系中扮演的功能称为实体的角色。
属性:实体集的属性是将实体集映射到域的函数。因为一个实体集可能有多个属性,所以每一个实体能够用一组(属性,数据值)对来表示,实体集的每一个属性对应一个这样的对。
联系集的度:参与联系集的实体集的数目。
给定的联系集中的联系实例必须是由其参与实体惟一标识的。
相同的 实体集可能会参与到多于一个联系集中
每一个属性都有一个可取值的集合,称为该属性的域,或则值集
E-R模型中的属性能够按照以下的属性类型来划分
(1)简单和复合属性:简单属性指不能划分为更小的部分;复合属性指能够再划分为更小的部分(即其余属性)。例如属性name可设计为一个包含first_name、middle_initial和last_name的复合属性
(2)单值和多值属性:咱们直接用例子说明:对某个特定的学生实体而言,student_ID属性只对应于一个学生ID,这样的属性为单值;在教师实体中,每一个教师能够有0个、1个或多个电话号码,这个phone_number属性就是多值的。{}
(3)派生属性:这类属性的值能够从别的相关属性或实体派生出来。派生属性的值不存储,在须要的时候计算出来
映射基数:表示一个实体经过一个联系集能关联的实体的个数。
(1)一对一:A中的一个实体至多与B中的一个实体相关联,而且B中的一个实体也至多与A中的一个实体相关联
(2)一对多:A中的一个实体至多与B中的零个或多个实体相关联,而B中的一个实体也至多与A中的一个实体相关联
(3)多对一:A中的一个实体至多与B中的一个实体相关联,而B中的一个实体能够与A中的零个或多个实体相关联
(4)多对多:A中的一个实体至多与B中的零个或多个实体相关联,并且B中的一个实体也能够与A中的零个或多个实体相关联
若是实体集E中的每一个实体都参与到联系集的至少一个联系之中,实体集E在联系集R中的参与称为所有的。若是实体集E中只有部分实体参与到联系集的之中,实体集E在联系集R中的参与称为部分的。
关系模式中的超码、候选码、主码的概念一样适用于实体集
分红两部分的矩形:表明实体集,上面的第一部分为实体集的名字,下面的第二部分包含实体集中全部属性的名字
菱形:表明联系集
未分割的矩形:表明联系集的属性,构成主码的属性如下划线代表
线段:将实体集链接到联系集
虚线:将联系集属性链接到联系集
双线:显示实体在联系集中的参与度
双菱形:表明链接到弱实体集的标志性联系集
联系集和实体集之间也有映射基数,意思同约束中的映射技术,联系集为实体A,实体集为实体B
约束的方式有两种:
1、
2、用l..h的形式表示一个关联的最小和最大的映射基数
表示方法:
name、address、street为复合属性
{phone_number}为多值属性
{age()}为派生属性age
经过在菱形和矩形之间的连线上进行标注来表示角色,例以下图中的course_id和prereq_id
咱们至多容许一个箭头
弱实体集:没有足够的属性以造成主码的实体集称做弱实体集
强实体集:有主码的实体集称做强实体集
弱实体集必须与另外一个称做标识或属主实体集的实体集关联才能有意义。每一个弱实体必须和一个标识实体关联;也就是说,弱实体集存在依赖于标识实体集。咱们称标识实体集拥有它所标识的弱实体集。将弱实体集与其标识实体集相联的联系称为标识性联系。
标识性联系是从弱实体集到强实体集多对一的,而且弱实体集在联系中的参与是所有的。标识性联系集不该该有任何描述性属性,由于这种属性中的任意一个均可以与弱实体集相关联。
分辨符:虽然弱实体集没有主码,可是咱们仍然须要区分依赖于特定强实体集的弱实体集中的实体的方法。弱实体集的分辨符是使咱们进行这种区分的属性集合,也称为该实体集的部分码。
弱实体集的主码由标识实体集的主码加上弱实体集的分辨符构成。
图形表示:
弱实体集的分辨符以虚下划线标明,而不是实线。
关联弱关系集和标识性强实体集的联系集用双菱形表示。
弱实体集能够参与标识性联系意外的联系。弱实体集能够做为属主与另外一个弱实体集参与一个标识性联系。一个弱实体集也可能与不止一个标识实体集相关联。这样,一个特定的弱实体集将被一个实体的组合标识,其中每一个标识实体集有一个实体在组合中。弱实体集的主码能够由标识实体集的主码加上弱实体集的分辨符构成。
若是弱实体集属性少,直接归并到实体集中。不然自成一家。
设E是只具备简单描述性属性a1,a2,...,an的强实体集。咱们用具备n个不一样属性的模式E来表示这个实体集。该模式的关系中的每一个远足同实体集E的一个实体相对应。
这个就比上面的状况复杂一点,咱们经过为每一个子属性建立一个单独的和属性来处理符合属性,咱们并不为复合属性自身建立一个单独的属性。
例如instructor实体集,里面有复合属性name,为instructor生成的末世包括属性first_name、middle_initial和last_name;没有单独的属性或末世表示name。其余属性相似。
对于一个多值属性M,构建关系模式R,该模式包含一个对应与M的属性A,以及对应于M所在的实体集或联系集的属性。
在一个实体集只有两个属性的状况下——一个主码B和多值属性M——该实体集的关系模式只含有一个属性,即主码属性B,能够删除这个关系,同时保留属性B和对应M的属性A的关系模式。
设A是具备属性a1,a2,...,am的弱实体集,设B是A所依赖的强实体集,设B的主码包括属性b1,b2,...,bn。咱们用名为A的关系模式表示实体集A,该模式的每一个属性对应如下集合中的一个成员:
因此A的模式的属性有:A的属性和B的主码。
该模式的主码由实体集B的主码和A的分辨符组成。
- 若实体间联系是1:1,能够在两个实体类型转换成的两个关系模式中任意一个关系模式的属性中加入另外一个关系模式的键(做为外键)和联系类型的属性。
- 若实体间联系是1:N,则在N端实体类型转换成的关系模式中加入1端实体类型的键(做为外键)和联系类型的属性。
- 若实体间联系是M:N,则将联系类型也转换成关系模式,其属性为两端实体类型的键(做为外键)加上联系类型的属性,而键为两端实体键的组合
考虑实体集A,B和联系集AB。假设A在该联系中的参与是所有的,那么咱们能够将A和AB合并称单个包含两个模式全部属性的并集的模式。
有损分解:分解关系的时候损失了信息。
无损分解:分解关系的时候没有损失了信息。
第一范式(1NF)
若是某个域的元素被认为是不可再分的单元,那么这个域就是原子的(atomic)。若是一个关系模式R的全部的属性域都是原子的,咱们称关系模式R属于第一范式(first normal form, 1NF)。
设R(U)是属性集U上的关系模式,α,β含于 U, r是R(U) 上的任意一个关系,若是成立
对于r中全部元组对t , s ∈ r,若t[α] = s[],则t[β] = s[β]
那么称“α函数决定β”,或“β函数依赖于α”,记做αβ
称α为决定因素,β为被决定因素。说该函数依赖在关系模式R(U)上成立
平凡函数依赖
若是αβ,但β不含于α,则称其为非平凡的函数依赖,不然(即β含于α)称为平凡(trivial)的函数依赖。如(sno,sname)sname是平凡的函数依赖。
范式是对关系的不一样数据依赖程度的要求。经过模式分解将一个低级范式转换为若干个高级范式的过程称做规范化。
1NF
关系中每一份量不可再分。即不能以集合、序列等做为属性值。
2NF
若R∈1NF,且每一个属性知足下列准则之一:
它出如今一个候选码中
它没有部分依赖于一个候选码,则称R∈2NF。
2NF消除了非主属性对码的部分依赖.
3NF
关系模式R< U , F >中,F+中全部函数依赖αβ ,至少有如下之一成立 :
① αβ是平凡的函数依赖;
② α是超码;
③ β-α的每个属性A都包含在R的候选码中,则称R∈3NF。
3NF消除了非主属性对码的传递依赖。
做为判断3NF时的一种优化,能够只考虑F上的函数依赖,而不是F+,也能够分解F上的函数依赖,让它们的右半部只包含一个属性,并用这个结果代替F。
3NF的判断被证实是没法求解的,是NP问题。
BCNF
关系模式R< U , F >中,全部的形如αβ的函数依赖( α∈U,β∈U ),下面至少有一个成立:
① αβ是平凡的函数依赖;
2.α是模式R的一个超码,则称R∈BCNF。
如SPC ∉ BCNF,由于tnocno,而tno不是超码。
改造:将S分解为:(sno,tno),(tno,cno)。
BCNF分解:
咱们对函数依赖进行数据库设计的目标:
无损分解:
被F所逻辑蕴涵的函数依赖的全体所构成的集合称做F的闭包。
Armstrong公理系统
各希腊字母都为属性集
自反律:若β含于α,则αβ
增补率:若αβ,则αγβγ
传递率:若αβ,βγ,则αγ
合并率:若αβ,αγ,则αβγ
分解率:若αβγ,则αβ,αγ
伪传递率:若αβ,γβδ,则γαδ
属性集的闭包
令α为属性集,将函数依赖集F下被α函数肯定的全部属性的集合称做F下α的闭包,记做α+
α+= {A |αA能由F根据Armstrong公理导出}。能够求候选码
范式是对关系的不一样数据依赖程度的要求。经过模式分解将一个低级范式转换为若干个高级范式的过程称做规范化。
1NF
关系中每一份量不可再分。即不能以集合、序列等做为属性值。
2NF
若R∈1NF,且每一个属性知足下列准则之一:
它出如今一个候选码中
它没有部分依赖于一个候选码,则称R∈2NF。
2NF消除了非主属性对码的部分依赖.
3NF
关系模式R< U , F >中,F+中全部函数依赖αàβ ,至少有如下之一成立 :
① αàβ是平凡的函数依赖;
② α是超码;
③ β-α的每个属性A都包含在R的候选码中,则称R∈3NF。
3NF消除了非主属性对码的传递依赖。
做为判断3NF时的一种优化,能够只考虑F上的函数依赖,而不是F+,也能够分解F上的函数依赖,让它们的右半部只包含一个属性,并用这个结果代替F。
3NF的判断被证实是没法求解的,是NP问题。
BCNF
关系模式R< U , F >中,全部的形如αàβ的函数依赖( α∈U,β∈U ),下面至少有一个成立:
1.αàβ是平凡的函数依赖,
2.α是模式R的一个超码,则称R∈BCNF。
如SPC ∉ BCNF,由于tnoàcno,而tno不是超码。
改造:将S分解为:(sno,tno),(tno,cno)。
多值依赖
对称性,函数依赖是多值依赖的特例,传递性
函数依赖好多值依赖区别
函数依赖规定某些元组不能出如今关系中,也称为相等产生依赖。
多值依赖要求某种形式的其它元组必须在关系中,称为元组产生依赖。
闭包
令D表示函数依赖和多值依赖的集合,D的闭包D+是由D逻辑蕴涵的全部函数依赖和多值依赖的集合。
4NF
函数依赖和多值依赖集为D的关系模式R属于4NF的条件是:对于全部D+中形如: αààβ的多值依赖(其中α包含于R∧β包含于R),至少有如下条件之一成立:
1.αàà β是一个平凡的多值依赖;
2.α是模式R的超码,则称R∈4NF。
如关系模式TEACH,cnoààtno,cnoààbno,码为(cno, tno, bno),因此CTB∉4NF。改造:将CTB分解为CT(cno,tno),CB(cno,bno),在分解后的关系中份量为Ci的元组共有m + n个
4NF的本质
(在只考虑函数和多值依赖的前提下),4NF只讲一件事,非码的多值决定关系讲述了另一件事。
R(cno,bno,tno)
cno→→bno
cno→→tno
R讲述了(cno,bno)和(cno,tno)两件事。
有效且完备的公理系统
范式之间的关系
1NF:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。
2NF:1NF的基础上,非码属性必须彻底依赖于码。在1NF基础上消除非主属性对主码的部分函数依赖。
3NF:在1NF基础上,任何非主属性不依赖于其它非主属性。在2NF基础上消除传递依赖。
BCNF:在1NF基础上,任何非主属性不能对主键子集依赖,在3NF基础上消除对主码子集的依赖。
4NF:在多值依赖的视角评价关系模式。
解除规范化
把一个规范化的模式变成非规范化的过程。目的:用于调整系统的性能
事务是做为单个逻辑工做单元执行的一系列数据库操做。这些操做要么都作,要么都不作,是一个不可分割的工做单位
事务是访问并可能更新各类数据项的一个程序执行单元。
事物特性(ACID)
原子性(Atomicity)
事务中包含的全部操做要么全作,要么全不作。原子性由恢复系统实现。
一致性(Consistency)
事务的隔离执行必须保证数据库的一致性。事务开始前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态;事务的执行过程当中能够暂时的不一致。数据库的一致性状态由用户来负责,由并发控制系统实现。
如银行转帐,转帐先后两个账户金额之和应保持不变。
隔离性(Isolation)
系统必须保证事务不受其它并发执行事务的影响。对任何一对事务T1,T2,在T1看来,T2要么在T1开始以前已经结束,要么在T1完成以后再开始执行。隔离性经过并发控制系统实现。
持久性(Durability)
一个事务一旦提交以后,它对数据库的影响必须是永久的。系统发生故障不能改变事务的持久性。持久性经过恢复系统实现。
因为故障,系统的状态再也不反应数据库本应描述的现实世界的真实状态,咱们把这种状态称为不一致状态。
恢复系统保证原子性和持久性。并发控制系统保证隔离性和一致性。
一旦事务已提交,咱们不能经过停止他来撤销其形成的影响,撤销已提交事务形成的影响的惟一方法就是执行一个补偿事务。书写一个补偿事务的责任留给用户
事务的几种状态:
一、活跃的:初始状态,事务开始执行时处于这个状态
二、部分提交的:最后一条语句执行后。可能发生硬件故障。当数据库往磁盘上写了足够的信息,确保即便发生硬件故障更新也能在系统重启时建立。当最后一条这样的信息写完以后,事务进入提交状态。
三、失败的:发现正常的执行不能继续后
四、停止的:事务回滚而且数据库恢复到事务执行以前的状态后
五、提交的:成功执行后
状态转换图以下:若是事务是提交的或则终止的,咱们称事务是已经结束的
事务进入停止状态后,系统这时候有两种选择:
一、重启事务:当且仅当停止是由硬件错误形成的或者不是事物自己逻辑所产生的错误时。重启的事务会被当作一个新的事务
二、杀死事务:若是停止是由事务内部逻辑错误致使的那么事务就会被杀死。当处理可见的外部写,好比写到屏幕上必定要当心。大多数系统只容许在操做在事务进入提交状态后发生。
两条很好的理由容许并发:
- 提升吞吐量和资源利用率
- 减小等待时间
事务调度
- 事务的执行顺序称为一个调度(schedule),表示事务的指令在系统中执行的时间顺序。
串行调度:属于同一事务的指令在调度中紧挨在一块儿
可串行化调度:并发执行中,保证所执行的任何调度的效果与没有并发执行的调度效果同样。这样能够保证数据库的一致性。调度应该在某种意义上等价与一个串行调度。这种调度称为可串行化调度。
串行调度是可串行化的。
冲突指令:
当两条指令是不一样事务在相同数据项上的操做,而且其中至少有一个是write指令时,则称这两条指令是冲突的。
冲突等价:
若是调度S能够通过一系列非冲突指令交换转换成调度S',则称调度S与S'是冲突等价的(conflictequivalent)。不是全部的串行调度都冲突等价。
冲突可串行化:
当一个调度S与一个串行调度冲突等价时,则称该调度S是冲突可串行化的
一个事务失败了,应该可以撤消该事务对数据库的影响。若是有其它事务读取了失败事务写入的数据,则该事务也应该撤消。
可恢复调度:
对于每对事务T1与T2,若是T2读取了T1所写的数据,则T1必须先于T2提交。
级联调度:
因为一个事务故障而致使一系列事务回滚。
无级联调度:
对于每对事务T1与T2,若是T2读取了T1所写的数据,则T1必须在T2读取以前提交。
<注>无级联调度必是可恢复调度
并发操做带来的数据不一致性
(1)丢失修改(Lost Update)
两个事务T1和T2读入同一数据并修改,T2的提交结果破坏了T1提交的结果,致使T1的修改被丢失。
(2)不可重复读(Non-repeatable Read)
不可重复读是指事务T1读取数据后,事务T2执行更新操做,使T1没法再现前一次读取结果。不可重复读包括三种状况:
- 事务T1读取某一数据后,事务T2对其作了修改,当事务T1再次读该数据时,获得与前一次不一样的值
- 事务T1按必定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神秘地消失了。
- 事务T1按必定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。
后两种不可重复读有时也称为幻影现象(Phantom Row)
(3)读“脏”数据(Dirty Read)
读“脏”数据是指:
事务T1修改某一数据,并将其写回磁盘
事务T2读取同一数据后,T1因为某种缘由被撤销
这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致
T2读到的数据就为“脏”数据,即不正确的数据。事务隔离性
按照隔离级别从低到高的顺序:
未提交读:容许读取未提交数据。(当事务A更新某条数据时,不允许其余事务来更新该数据,但能够读取。)
已提交读:只容许读取已提交数据,但不要求可重复读。(当事务A更新某条数据时,不允许其余事务进行任何操做包括读取,但事务A读取时,其余事务能够进行读取、更新。)
可重复读:只容许读取已提交数据,并且一个事务两次读取一个数据项期间,其余事务不得更新该数据,可是该事务不要求与其余事务可串行化。
可串行化:保证可串行化调度。
以上全部隔离级别都不容许脏写,即若是一个数据项已经被另一个还没有提交的事务写入,则不容许对该数据项执行写操做。
并发控制机制的任务:对并发操做进行正确调度、保证事务的隔离性、保证数据库的一致性。
基本封锁类型:
共享锁
共享锁又称为读锁。若事务T对数据对象Q加上S锁,事务T可读但不能写Q,其它事务只能再对Q加S锁,而不能加X锁,直到T释放Q上的S锁。
排它锁
排它锁又称为写锁。若事务T对数据对象Q加上X锁,则事务T既能够读又能够写Q,其它任何事务都不能再对Q加任何类型的锁,直到T释放A上的锁。
假设对于某对象,事物j请求A型锁,事物i拥有B型锁。若是事物j能够马上获得A型锁。则称A与B锁是相容的。
让事务在对数据项最后一次访问后当即释放锁也未必是可取的,由于可能不能保证可串行化。
死锁:一种哪一个事物都不能正常执行的状态。当死锁发生时,必须回滚两个事务中的一个。
饥饿/饿死:
不断出现的申请并得到S锁的事务,使申请X锁的事务一直处在等待状态。
饥饿的防止:
对申请S锁的事务,若是有先于该事务且等待的加X锁的事务,令申请S锁的事务等待。
定义:每一个事务分两个阶段提出加锁和解锁申请。
增加阶段(growing phase):事务能够得到锁,但不能释放锁。
缩减阶段(shrinking phase):事务能够释放锁,但不能得到新锁。
封锁点(lock point):事务最后加锁的位置,称为事务的封锁点, 记做Lp(T)。
并行执行的全部事务均遵照两段锁协议,则对这些事务的全部并行调度策略都是可串行化的。全部遵照两段锁协议的事务,其并行执行的结果必定是正确的。
事务遵照两段锁协议是可串行化调度的充分条件,而不是必要条件。可串行化的调度中,不必定全部事务都必须符合两段锁协议。
两阶段封锁协议不保证不会发生死锁。
严格两阶段封锁协议:除了要求封锁是两阶段以外,还要求事务持有的全部排他锁必须在事务结束后,方可释放。
强两阶段封锁协议:事务提交以前,不得释听任何锁。在强两阶段封锁协议下,事务能够按其结束的顺序串行化。
事务访问数据的粒度不一样
DB、Table、Tuple、…
单一封锁粒度的问题
封锁粒度大:并发性低
封锁粒度小:访问大粒度数据加锁量巨大
多粒度封锁:根据访问数据的粒度,肯定封锁的粒度。以求加锁量有限,并可得到最大的并发性
多粒度封锁的基本原则:
大粒度数据由小粒度数据组成;
容许对不一样粒度数据进行封锁;
事务对大粒度数据加锁,隐含地对组成大粒度数据的全部小粒度数据加锁。
多粒度层次结构
多粒度层次树,子节点表示的数据是父节点表示数据的一部分。
意向锁(intention lock mode)
若是一个节点加上了意向锁,则意味着要在树的较低层进行显示加锁。
在一个节点显式加锁以前,该结点的所有祖先均加上了意向锁。
事务断定是否可以成功地给一个结点加锁时,没必要搜索整棵树。
多粒度封锁相容矩阵
共享意向锁(IS)/排他意向锁(IX)/共享排他意向锁(SIX)
多粒度封锁协议:
特色:
增长了并发行,减小了锁开销。
适应范围:
只存取几个数据项的短事务,
由整个文件或一组文件造成报表的长事务。
释放顺序:多粒度协议要求加锁按照自顶向下的顺序,而锁的释放按照自底向上的顺序
1.事务内部的故障:
(1)有的是能够经过事务程序自己发现的。
(2)有的是非预期的,不能由事务程序处理的。
事务内部更多的故障是非预期的,是不能由应用程序处理的
(1)运算溢出 逻辑错误
(2)并发事务发生死锁而被选中撤销该事务 系统错误
(3)违反了某些完整性限制而被终止等 逻辑错误
之后,事务故障仅指这类非预期的故障
2.系统崩溃
一、系统故障
称为软故障,是指形成系统中止运转的任何事件,使得系统要从新启动。
(1)整个系统的正常运行忽然被破坏
(2)全部正在运行的事务都非正常终止
(3)不破坏数据库
(4)内存中数据库缓冲区的信息所有丢失
二、系统故障的常见缘由
(1)特定类型的硬件错误(如CPU故障)
(2)操做系统故障
(3)数据库管理系统代码错误
(4)系统断电
3.磁盘故障
称为硬故障,指外存故障
(1)磁盘损坏
(2)磁头碰撞
(3)瞬时强磁场干扰
介质故障破坏数据库或部分数据库,并影响正在存取这部分数据的全部事务
介质故障比前两类故障的可能性小得多,但破坏性大得多
咱们把存储器分红3类:非易失性存储器、易失性存储器、稳定存储器
各种故障,对数据库的影响有两种可能性
一是数据库自己被破坏
二是数据库没有被破坏,但数据可能不正确,这是因为事务的运行被非正常终止形成的。
恢复算法两部分:
磁盘中的块:物理块。主存中的块:缓冲块。内存中临时用来存放块的区域:磁盘缓存区。
缓冲块最终被写道磁盘上,要么是应为缓冲区管理器用于其它用途,要么是由于数据库系统但愿将B的变化映射到磁盘上。后一种称为数据库系统对缓冲块强制输出。
(1)恢复操做的基本原理:冗余
利用存储在系统别处的冗余数据来重建数据库中已被破坏或不正确的那部分数据
(2)恢复的实现技术:复杂
一个大型数据库产品,恢复子系统的代码要占所有代码的10%以上
恢复机制涉及的关键问题
1. 如何创建冗余数据
数据转储(backup):转储是指数据库管理员按期地将整个数据库复制到磁带、磁盘或其余存储介质上保存起来的过程
登记日志文件(logging)
2.转储方法
在系统中无运行事务时进行的转储操做
转储操做与用户事务并发进行
日志文件(log file):是用来记录事务对数据库的更新操做的文件
以记录为单位的日志文件,每条日志记录的内容:
一些日志记录类型:<T start><T commit><T abort>
为何要先写日志文件
写数据库和写日志文件是两个不一样的操做
在这两个操做之间可能发生故障
若是先写了数据库修改,而在日志文件中没有登记下这个修改,则之后就没法恢复这个修改了
若是先写日志,但没有修改数据库,按日志文件恢复时只不过是多执行一次没必要要的UNDO操做,并不会影响数据库的正确性
为了保证故障恢复时能使用日志文件,日志必须存放在稳定存储器中。
12.7.3.2 数据库修改
若是一个事务直到提交时都没有修改数据库,咱们称它采用了延迟修改。若是数据库修改数据库时事务仍活跃,咱们称它使用了当即修改。
对于事物的undo完成后,写一个abort日志记录,代表撤销完成了
当一个事务的commit日志记录输出到稳定存储器后,咱们说这个事务提交了。若是系统崩溃在commit日志记录输出到稳定存储器以前,事务将回滚。
故障的恢复
系统故障形成数据库不一致状态的缘由
(1)未完成事务对数据库的更新可能已写入数据库
(2)已提交事务对数据库的更新可能还留在缓冲区没来得及写入数据库
恢复方法
(1) Undo 故障发生时未完成的事务
(2) Redo 已完成的事务
系统故障的恢复由系统在从新启动时自动完成,不须要用户干预
(1)正向扫描日志文件(即从头扫描日志文件) 事务故障反向
重作(REDO) 队列: 在故障发生前已经提交的事务
这些事务既有BEGIN TRANSACTION记录,也有COMMIT记录或abort记录
撤销 (UNDO)队列:故障发生时还没有完成的事务
这些事务只有BEGIN TRANSACTION记录,无相应的COMMIT记录或abort记录
(2) 对撤销(UNDO)队列事务进行撤销(UNDO)处理
反向扫描日志文件,对每一个撤销事务的更新操做执行逆操做
即将日志记录中“更新前的值”写入数据库
(3)对重作(REDO)队列事务进行重作(REDO)处理
正向扫描日志文件,对每一个重作事务从新执行登记的操做
即将日志记录中“更新后的值”写入数据库
一、两个问题
(1)搜索整个日志将耗费大量的时间
(2)重作处理:从新执行,浪费了大量时间
二、解决方案
具备检查点(checkpoint)的恢复技术
(1)在日志文件中增长检查点记(checkpoint)。
(2)增长从新开始文件。
(3)恢复子系统在登陆日志文件期间动态地维护日志。
10.6.2.检查点技术
一、检查点记录的内容
(1)创建检查点时刻全部正在执行的事务清单
(2)这些事务最近一个日志记录的地址
二、从新开始文件的内容
记录各个检查点记录在日志文件中的地址
三、动态维护日志文件的方法
周期性地执行以下操做:创建检查点,保存数据库状态。
具体步骤是:
(1)将当前日志缓冲区中的全部日志记录写入磁盘的日志文件上
(2)在日志文件中写入一个检查点记录
(3)将当前数据缓冲区的全部数据记录写入磁盘的数据库中
(4)把检查点记录在日志文件中的地址写入一个从新开始文件
四、创建检查点
恢复子系统能够按期或不按期地创建检查点,保存数据库状态:
按期:按照预约的一个时间间隔,如每隔一小时创建一个检查点
不按期:按照某种规则,如日志文件已写满一半创建一个检查点
10.6.3.利用检查点的恢复策略 一、使用检查点方法能够改善恢复效率 (1)当事务T在一个检查点以前提交,T对数据库所作的修改已写入数据库。 (2)写入时间是在这个检查点创建以前或在这个检查点创建之时。 (3)在进行恢复处理时,没有必要对事务T执行重作操做 二、利用检查点的恢复步骤 (1)从从新开始文件中找到最后一个检查点记录在日志文件中的地址,由该地址在日志文件中找到最后一个检查点记录 (2)由该检查点记录获得检查点创建时刻全部正在执行的事务清单ACTIVE-LIST 创建两个事务队列 UNDO-LIST REDO-LIST 把ACTIVE-LIST暂时放入UNDO-LIST队列,REDO队列暂为空。 (3)从检查点开始正向扫描日志文件,直到日志文件结束 若有新开始的事务Ti,把Ti暂时放入UNDO-LIST队列 若有提交的事务Tj,把Tj从UNDO-LIST队列移到REDO-LIST队列;直到日志文件结束 (4)对UNDO-LIST中的每一个事务执行UNDO操做 对REDO-LIST中的每一个事务执行REDO操做