关系数据库基础知识

数据库的学习,主要分为几个部分(按时间顺序123进行):

1. 关系数据库基础知识

CyC2018/CS-Notes/blob/master/notes/数据库系统原理

2. MySQL的语法(PHP)

《MySQL必知必会》

CyC2018/CS-Notes/blob/master/notes/SQL

CyC2018/CS-Notes/blob/master/notes/MySQL

牛客MySQL入门教程

3. MySQL上机实战训练&选择题

MySQL上机实战训练

选择题专练 

-------------------------------------------------------------------------

 下面是正文:

 

 

第一步:关系数据库基础知识     

参考 CyC2018/CS-Notes/blob/master/notes/数据库系统原理

 

事务:

关系数据库基础知识_第1张图片

 

 

ACID

A:atomic原子性

C:consistency一致性

I:isolation隔离性

D:durability持久性

 

A:事务不可分割的最小单元,事务的操作(c、r、u、d)要么全成功,要么失败全部回滚(Undo Log)   "Ctrl+Z"

C:多个事务,对同一个数据的:读/写,获取相同结果

I:  在Commit(提交)之前,做的修改其他人(事务)看不见

D: 数据安全持久保存:崩溃后恢复,重做日志(Redo Log)

 

关系数据库基础知识_第2张图片

 

 

 

并发一致性问题

  • 修改丢失 (覆盖) 
  • 脏读 (撤销修改,中间状态被别的捕获)(两个事务的读)
  • 不可重复读(连读2次不一样,因为中间有别的修改了)(同一个事务两次读)
  • 幻影读(类似上条,不同的是获取:间接数据)

关系数据库基础知识_第3张图片

T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。

 

 

 关系数据库基础知识_第4张图片

T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了修改,那么 T2 读取的数据是脏数据。

 

 

关系数据库基础知识_第5张图片

T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。

 

 

关系数据库基础知识_第6张图片

T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。

 

并发性 <==> 隔离性

在并发环境下,事务的隔离性很难保证因此会出现很多并发一致性问题。

解决方法:通过 并发控制 来保证 隔离性。

并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。

 

 

 

封锁

锁粒度

  • 粒度越大,锁争用越大,并发度越小
  • 粒度越小,系统开销越大

MySQL两种粒度:行级锁、表级锁

 

1.读写锁

  • 读锁(共享锁Share)S锁
  • 写锁(互斥锁)X锁

 关系数据库基础知识_第7张图片

 

2.意向锁

意向锁(Intention Locks)可以更容易地支持多粒度封锁

IS/IX 对行加锁;S/X对整个表加锁

关系数据库基础知识_第8张图片

 红框是原来2X2的读写锁(S/X)就有的,

绿框新增的兼容性,包括:IS与IX,IX与IX

 

 

封锁协议

三级封锁协议(层层递进,越来越严格)

  • 一级封锁协议   修改时,X锁|整个事务T  阻止其他修改(读时不阻止)==》 防止"修改丢失"
  • 二级封锁协议   读时 ,S锁|读完释放  阻止其他修改  ==》 增加:防止"脏读"
  • 三级封锁协议   读时 ,S锁|整个事务T  阻止其他修改  ==》 增加:防止"不可重复读"

二级封锁协议补充:可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。

 

 

两段锁协议 (两个阶段):加锁、解锁

第一阶段全部是加锁,第二阶段全部解锁(开始解锁后就不能开始任何加锁了):

事务遵循两段锁协议是保证可串行化调度的充分条件。例如上面的操作满足两段锁协议,它是可串行化调度。

 可串行化调度:通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题。

 但不是必要条件,例如上面操作不满足两段锁协议,但它还是可串行化调度。

 

MySQL 默认隐式锁定(使用两段锁协议) / 也可手动切换显式锁定

 MySQL 的 InnoDB 存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁都是在同一时刻被释放,这被称为隐式锁定。

 

 

隔离级别

  • 未提交读:未提交的修改,对其他事物可见
  • 提交读:未提交的修改,其他事物不可见【解决:脏读】
  • 可重复读:多次读取结果一样【解决:不可重复读】
  • 可串行化:串行互不干扰,并发一致性问题不出现(需要加锁保证,同一时间仅一事务)

关系数据库基础知识_第9张图片

 

 

 

多版本并发控制(Multi-Version Concurrency Control, MVCC)

  • 未提交读:无须MVCC 
  • 提交读+可重复读:适合MVCC
  • 可串行化:MVCC无法实现读写行都加锁

基本思想

MVCC修改操作(增删改)会创建版本快照

脏读不可重复读最根本的原因是事务读取到其它事务未提交的修改

在事务进行读取操作时,为了解决脏读和不可重复读问题,MVCC 规定只能读取已经提交的快照

版本号

  • 系统版本号  SYS_ID   每个新事务自动递增
  • 事务版本号  TRX_ID

Undo日志

MVCC的多版本快照,存储在Undo日志中,通过回滚指针连接快照。

例如:

关系数据库基础知识_第10张图片

关系数据库基础知识_第11张图片

 

 

ReadView(MVCC) (??这里不是很懂)

关系数据库基础知识_第12张图片

在进行 SELECT 操作时,根据数据行快照的 TRX_ID 与 TRX_ID_MIN 和 TRX_ID_MAX 之间的关系,从而判断数据行快照是否可以使用:

  • TRX_ID < TRX_ID_MIN,表示该数据行快照时在当前所有未提交事务之前进行更改的,因此可以使用。

  • TRX_ID > TRX_ID_MAX,表示该数据行快照是在事务启动之后被更改的,因此不可使用。

  • TRX_ID_MIN <= TRX_ID <= TRX_ID_MAX,需要根据隔离级别再进行判断:

    • 提交读:如果 TRX_ID 在 TRX_IDs 列表中,表示该数据行快照对应的事务还未提交,则该快照不可使用。否则表示已经提交,可以使用。
    • 可重复读:都不可以使用。因为如果可以使用的话,那么其它事务也可以读到这个数据行快照并进行修改,那么当前事务再去读这个数据行得到的值就会发生改变,也就是出现了不可重复读问题。
  • 快照读 读不加锁?

  MVCC的 SELECT 操作是快照中的数据,不需要进行加锁操作。

  • 当前读 改加锁?

   MVCC 其它会对数据库进行修改的操作(INSERT、UPDATE、DELETE)需要进行加锁操作,从而读取最新的数据。可以看到 MVCC 并不是完全不用加锁,而只是避免了 SELECT 的加锁操作。

  在进行 SELECT 操作时,可以强制指定进行加锁操作。以下第一个语句需要加 S 锁,第二个需要加 X 锁:

SELECT * FROM table WHERE ? lock in share mode;
SELECT * FROM table WHERE ? for update;

 

Next-Key Locks =>用于解决幻影读问题     (??这里不是很懂)

MVCC 不能解决幻影读问题,Next-Key Locks 就是为了解决这个问题而存在的。在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。

  • Record Locks : 锁定一个记录上的索引,而不是记录本身。

  • Gap Locks :锁定索引之间的间隙,但是不包含索引本身。

  • Next-Key Locks: 双管齐下Record Locks + Gap Locks. 不仅锁定一个记录上的索引,也锁定索引之间的间隙。

  

 

关系数据库设计理论

函数依赖

  • 依赖:记 A->B 表示 A 函数决定 B         其中A={A1,A2...An}  B={B1,B2...Bm}也就是A/B都有若干属性
  • 部分依赖:A存在子集A'  这时候A'就可以决定B
  • 完全依赖:A->B,其中A为最小集

  对于 A->B,B->C,则 A->C 是一个传递函数依赖。

异常

以下的学生课程关系的函数依赖为 {Sno, Cname} -> {Sname, Sdept, Mname, Grade},键码为 {Sno, Cname}。

也就是说,确定学生Sno和课程Cname之后,就能确定其它信息: 

关系数据库基础知识_第13张图片

不符合范式的关系,会产生很多异常,主要有以下四种异常:

  • 冗余数据:例如 学生-2 出现了两次。
  • 修改异常:修改了一个记录中的信息,但是另一个记录中相同的信息却没有被修改。
  • 删除异常:删除一个信息,那么也会丢失其它信息。例如删除了 课程-1 需要删除第一行和第三行,那么 学生-1 的信息就会丢失。
  • 插入异常:例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。

 

范式 NF

范式理论是为了解决以上提到四种异常。

高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。

关系数据库基础知识_第14张图片

  • 1NF  属性不可分
  • 2NF  非主属性完全函数依赖于键码(可以通过分解来满足)
  • 3NF  非主属性不传递函数依赖于键码。(不存在传递依赖)
  • BCNF 

 

例子:

关系数据库基础知识_第15张图片

(1)符合1NF:  属性不可分(上图)

函数依赖:

  • Sno, Cname-> Grade    //Grade 完全函数依赖于键码,它没有任何冗余数据,每个学生的每门课都有特定的成绩。
  • Sno -> Sname, Sdept    //部分依赖
  • Sdept -> Mname          //Sname, Sdept 和 Mname 都部分依赖于键码,当一个学生选修了多门课时,这些数据就会出现多次,造成大量冗余数据。

拆分:部分依赖的全部拆出来建新表,这样减少冗余:

关系数据库基础知识_第16张图片关系数据库基础知识_第17张图片

(2)符合2NF:  无部分依赖(上图)

上面的 关系-1 中存在以下传递函数依赖:

  • Sno -> Sdept -> Mname

于是,将关系1分解消除传递;关系2不变:

关系数据库基础知识_第18张图片关系数据库基础知识_第19张图片

 (3)符合3NF:  无传递(非主属性)(上图)

一般数据库到3NF就行了:

没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余,目的是达到:时间换空间

 

 

ER图 

三个组成部分:实体、属性、关系:

关系数据库基础知识_第20张图片

实体的三种关系

1对1, 1对n, n对n

  • 如果 A 到 B 是1对n关系,那么画个带箭头的线段指向 B;
  • 如果是1对1,画两个带箭头的线段;
  • 如果是n对n,画两个不带箭头的线段。

下图的 Course 和 Student 是1对n的关系:

关系数据库基础知识_第21张图片??

多重关系图

一个实体在联系出现几次,就要用几条线连接。

下图表示一个课程的先修关系,先修关系出现两个 Course 实体,第一个是先修课程,后一个是后修课程,因此需要用两条线来表示这种关系:

关系数据库基础知识_第22张图片

表示子类

用一个三角形和两条线来连接类和子类,与子类有关的属性和联系都连到子类上,而与父类和子类都有关的连到父类上。

关系数据库基础知识_第23张图片

 

你可能感兴趣的:(关系数据库基础知识)