1、概念
1)、主键
数据库表中对储存数据对象予以唯一和完整标识的数据列或属性组合,一个数据列只能有一个主键,且主键的值不能缺失,即不能为空值(NULL).
2)、超键
在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以作为一个超键,多个属性也可以作为一个超键。超键包含候选键和主键。
3)、候选键
是最小的超键,即没有冗余的超键。
4)、外键
在一个表中存在的另一个表的主键称此表的外键。

| id | 班级 | 班级中的学号 | 姓名 | 性别 | 年龄 |
|---|---|---|---|---|---|
| 001 | 1901 | 01 | 小明 | 男 | 22 |
| 002 | 1901 | 02 | 小红 | 女 | 21 |
| 003 | 1902 | 01 | 小李 | 男 | 24 |
| 004 | 1903 | 01 | 小王 | 男 | 23 |
| 005 | 1904 | 01 | 小明 | 男 | 22 |
| id | student_id | score |
|---|---|---|
| 001 | 001 | 100 |
| 002 | 004 | 99 |
| 003 | 005 | 95 |
候选键:
{id}、{班级、班级中的学号}
主键:
{id}或者{班级、班级中的学号}其中之一
超键:
{id、姓名}、{id、姓名、性别}、{班级、班级中的学号、姓名}、{id、姓名、性别、年龄}
注意:这些键并不一定是某一列,可以是多列
外键
student_id是表table_student_info的主键,是表table_student_score的外键。
2、数据库范式
1)、第一范式(1NF)
在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库表中的每一列都是不可分割的基本数项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一个范式(1NF)中表的每一行只包含一个实例的信息。简而言之,第一范式就是无重复的列。
不满足第一范式:
| id | 地址 |
|---|---|
| 001 | 海淀区西土城路10号,010-123456 |
| 002 | 海淀区学院路101号,010-789462 |
| 003 | 海淀区清华北路20号,010-455445 |
满足第一范式:
| id | 地址 | 电话 |
|---|---|---|
| 001 | 海淀区西土城路10号 | 010-123456 |
| 002 | 海淀区学院路101号 | 010-789462 |
| 003 | 海淀区清华北路20号 | 010-455445 |
2)、第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键、主码。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。
满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情;
如下表:主键为订单编号,那么其他字段都要依赖于订单编号,但是产品名称并不依赖订单编号,所以这张表不满足第二范式,因为她既描述了产品信息也描述了订单信息。
| 订单编号 | 订购日期 | 产品编号 | 产品名称 |
|---|---|---|---|
| 001 | 2019-04-28 | 1001 | 手机 |
拆分如下:
| 订单编号 | 订购日期 |
|---|---|
| 001 | 2019-04-28 |
| 产品编号 | 产品名称 |
|---|---|
| 1001 | 手机 |
3)、 第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。
必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键);
以下:有冗余字段
| 订单编号 | 订购日期 | 产品编号 | 产品名称 | ... |
|---|---|---|---|---|
| 001 | 2019-04-28 | 1001 | 手机 | ... |
| 订单编号 | 订购日期 | 产品编号 |
|---|---|---|
| 001 | 2019-04-28 | 1001 |
3、数据库五大约束
1)、primary KEY:设置主键约束
2)、UNIQUE:设置唯一性约束,不能有重复值
3)、DEFAULT 默认约束,height DOUBLE(3,2)DEFAULT 1.2 height不输入是默认为1.2
4)、NOT NULL:设置非空约束,该字段不能为空
5)、FOREIGN key:设置外键约束
4、事务
是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
事务的隔离级别
在说事务的隔离级别之前,首先要理解以下三个概念:
1、脏读
脏读发生在事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的数据是无效的数据。这跟不可重复读类似,但是第二个事务不需要执行提交。
| 事务1 | 事务2 |
|---|---|
| select * from users where id=1 | |
| update users set age=21 where id=1 | |
| select * from users where id=1 | |
| COMMIT; |
2、不可重复读
在基于锁的并行控制方法中,如果在执行select时不添加读锁,就会发生不可重复读问题。
在多版本并行控制机制中,当一个遇到提交冲突的事务需要回退但却被释放时,会发生不可重复读问题。
| 事务1 | 事务2 |
|---|---|
| select * from users where id=1 | |
| update users set age=21 where id=1;COMMIT; | |
| select * from users where id=1 | |
| COMMIT; |
在上面这个例子中,事务2提交成功,他所做的修改已经可见。然而,事务1已经读取了一个其他的值。在序列化和可重复读的隔离界别中,数据管理系统会返回旧值,即在被事务2修改之前的值。在提交读和未提交读隔离级别下,可能会返回被更新的值,这就是“不可重复读”。
有两个策略可以防止这个问题的发生:
(1)推迟事务2的执行,直至事务1提交或者回退。这种策略在使用锁时应用。
(2)而在多版本并行控制中,事务2可以被先提交。而事务1,继续执行在旧版本的数据上。当事务1终于尝试提交时,数据库会检验它的结果是否和事务1、事务2顺序执行时一样。如果是,则事务1提交成功。如果不是,事务1会被回退。
3、幻读(虚读)
幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。
发生的情况:没有范围锁。
| 事务1 | 事务2 |
|---|---|
| select * from users where age between 10 and 30; | |
| insert into users values(3,'raven',24); | |
| select * from users where age between 10 and 30; |
那么不可重复读和幻读由什么区别呢?
1、不可重复读
不可重复读的重点是修改:同样的条件,你读取过的数据,再次读取出来发现值不一样了。
例子:
在事务1中,Raven读取了自己的工资为1000,操作并没有完成
con1=getConnection();
select salary from employee empId=“Raven”;
在事务2中,这时财务人员修改了Raven的工资为2000,并提交了事务。
con2=getConnection();
updata employee set salary=2000;
在事务1中,Raven再次读取自己的工资时,工资边为了2000
select salary from employee empId=“Raven”;
在一个事务中前后两次读取的结果并不一致,导致了不可重复读。
2、幻读
幻读的重点在于新增或者删除(数据条数变化)。同样的条件,第1次和第2次读出来的记录数不一样。
例子:
目前工资为1000的员工有10人。
事务1,读取所有工资为1000的员工。
con1=getConnection();
select * from employee where salary=1000;
共读取出10条记录。
这时另一个事务想employee表插入了一个员工记录,工资也为1000
con2=getConnection();
Insert into employee(emPid,salary) values(“Raven”,1000);
con2.commit();
事务1再次读取所有工资为1000的员工。
select * from employee where salary =1000;
工读取到了11条记录,这样就产生了幻读。
接下来说隔离级别:
1、Read UnCommitted(读未提交)
最低的隔离级别。一个事务可以读取另一个事务并未提交的更新结果
2、Read Committed(读提交)
大部分数据采用默认隔离级别。一个事务的更新操作结果只有在该事务提交之后,另一个事务才可以读取到同一笔数据更新后的结果。
3、Repeatable Read(重复读)
mysql的默认级别。整个事务过程中。对同一笔数据的读取结果是相同的,不管其他事务是否在堆共享数据进行更新,也不管更新提交与否。
4、Serializable(序列化)
最高隔离级别。所有事务操作依次顺序执行。注意这个导致并发度下降,性能最差。通常会使用其他并发级别加上相应的并发锁机制来取代他。
| 脏读 | 不可重复读 | 幻读 | |
|---|---|---|---|
| Read Uncommitted(读未提交) | Yes | Yes | Yes |
| Read committed(读提交) | No | Yes | Yes |
| Repeatable read(可重复读) | No | No | Yes |
| Serializable(序列化或串行化) | No | No | No |
https://www.cnblogs.com/balfish/p/8298296.html
3113



被折叠的 条评论
为什么被折叠?



