【数据库】(1)数据库系统原理

文章目录

  • 参考
  • 事务
    • 1. 概念
    • 2. 四大特性
    • 3. ACID关系
  • 并发一致性问题
    • 1. 修改丢失
    • 2. 脏读
    • 3. 不可重复读
    • 4. 幻影读
    • 1. 锁粒度
    • 2. 锁类型
  • 锁协议
    • 1. 三级锁协议
    • 2. 两段锁协议
    • 3.MySQL隐式与显示锁定
  • 隔离级别
    • 1. 未提交读
    • 2. 提交读
    • 3. 可重读读
    • 4. 可串行化
  • MySQL的隔离级别实现
  • 关系数据库理论
    • 1. 函数依赖
    • 2. 异常
    • 3. 范式
      • 3.1 1NF
      • 3.2 2NF
      • 3.3 3NF
  • ER图

参考

CyC2018/CS-Notes
详解第一范式、第二范式、第三范式、BCNF范式

事务

1. 概念

  • 事务时满足ACID特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。

2. 四大特性

  • 原子性
    事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚
  • 一致性
    数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。(不能有事务读取到旧数据,所有事务对同一数据的读取保持一致)
  • 隔离性
    一个事务所做的修改在最终提交以前,对其它事务是不可见的.(对用户来说,一个事务执行,不需要考虑其他事务正在并发执行)
  • 持久性
    一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失

3. ACID关系

  • 一个数据库系统需要保证一致性(执行结果正确),持久性(数据不丢失)
  • 一致性需要靠原子性隔离性来保证
  • 无并发时,事务串行执行,此时需要满足原子性
  • 有并发时,原子性隔离性都要保证
    【数据库】(1)数据库系统原理_第1张图片

并发一致性问题

  • 在存在并发的情况下,数据库需要解决事务的隔离性,从而保证一致性,如果没有保证,那么会出现下面的一些问题

1. 修改丢失

  • T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
    【数据库】(1)数据库系统原理_第2张图片
  • 这里T1和T2的隔离性没有保证,在T1看来,产生了错误的结果

2. 脏读

  • T1修改数据,T2读数据,T1继续修改数据,那么T2读的是脏数据

【数据库】(1)数据库系统原理_第3张图片

  • 这里T2在T1的事务还没结束,就读取到了中间数据

3. 不可重复读

  • 由于T1的修改导致T2两次读取结果不同

【数据库】(1)数据库系统原理_第4张图片

4. 幻影读

  • 跟不可重复读类似,幻影读针对范围内数据

【数据库】(1)数据库系统原理_第5张图片

  • T2在T1统计时插入了新数据

那么如何解决上述问题?

显然需要并发控制,即`加锁`,如果用户自己加锁可能比较复杂,数据库系统提供了事务的`隔离级别`,让用户处理并发一致性问题更简单。

1. 锁粒度

  • 表级锁行级锁
  • 表级锁锁定的数据量,锁争用可能性,系统的并发程度,系统开销
  • 行级锁锁定的数据量,锁争用可能性,系统的并发程度,系统开销
锁定的数据量 锁数量 并发程度 系统开销
表级锁
行级锁
  • 因此需要在锁粒度并发程度做权衡

2. 锁类型

  1. 读写锁
  • 排它锁(Exlusive,X锁,写锁),可以读写
  • 共享锁(Shared,S锁,读锁),只能读
  • 事务T1对A加写锁,事务T2不能对A加锁
  • T1对A加S锁,T2可以对A加S锁,不能加X锁
  1. 意向锁
  • 读写锁的问题:如果T1需要对表A加表的写锁,那么需要检测是否有其他事务对表A的任意一行加了锁,这是非常耗时的。
  • IX锁:写表的意向锁
  • IS锁:读表的意向锁
  • 事务在获取行的S锁之前,需要获取表的IS锁或更强的锁
  • 事务在获取行的X锁之前,需要先获取表的IX锁
  • 意向锁主要是对整表加锁使用的

锁协议

1. 三级锁协议

  • 一级锁协议
    T修改A时加X锁,T结束后释放锁
    可以解决修改丢失问题
  • 二级锁协议
    读加S锁,读完后立即释放S锁
    解决读脏数据问题
  • 三级锁协议
    读加S锁,事务结束后释放S锁
    解决不可重复读问题

2. 两段锁协议

  • 事务分为加锁和解锁两个阶段进行,在读写时都需要获取锁,如果未能获取锁,则等待,以便保证可串行化调度
  • lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)

3.MySQL隐式与显示锁定

  • MySQL的InnoDB引擎使用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有锁在同一时刻被释放,即隐式锁定
  • 在SQL语句中,可以指定显示锁定
SELECT ... LOCK IN SHARE MODE;# S锁
SELECT ... FOR UPDATE; # X锁

隔离级别

  • 从低到高依次为

1. 未提交读

  • 事务的修改在提交前对其他事务可见
  • 没有隔离,会造成脏读、不可重复读、幻影读

2. 提交读

  • 事务的修改在提交前对其他事物不可见
  • 不会造成脏读,但会造成不可重复读,幻影读。(如T1读取数据A→T2的事务修改A并提交→T1再次读取数据A)

3. 可重读读

  • 保证同一个事务多次读取同样数据的结果一样
  • 未解决幻影读

4. 可串行化

  • 强制事务串行执行,需要加锁实现
  • 不会存在并发一致性问题

MySQL的隔离级别实现

  • InnoDB采用多版本并发控制(MVCC)来实现提交读和可重复读这两种隔离级别
  • InnoDB采用Next-Key Locks实现加锁机制
  • 用MVCC的可重复读+Next-Key Locks可以解决幻影读问题

关系数据库理论

1. 函数依赖

  • A → B表示A决定B或B依赖于A(通俗讲 : 知道A就知道B)
  • 键码 : 能够决定其他所有属性的最小属性集合
  • 对于 A->B,如果能找到 A 的真子集 A’,使得 A’-> B,那么 A->B 就是部分函数依赖(B可以依赖于A的一部分),否则就是完全函数依赖(B完全依赖于A)。
  • 如果 A->B,B->C,则 A->C 是一个传递函数依赖。

2. 异常

  • 不符合范式的关系会产生异常
  • 冗余异常、修改异常、删除异常、插入异常

3. 范式

  • 定义:符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度
  • 数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF。一般在我们设计关系型数据库的时候,最多考虑到BCNF就够。符合高一级范式的设计,必定符合低一级范式,例如符合2NF的关系模式,必定符合1NF。

3.1 1NF

  • 关系中每个属性不可再分
  • 例:【数据库】(1)数据库系统原理_第6张图片
  • 这个关系不符合1NF,需要修改为
    在这里插入图片描述
  • 此时每个属性不可再分,满足1NF

3.2 2NF

  • 每个非主属性完全函数依赖于键码
  • 例:
    【数据库】(1)数据库系统原理_第7张图片
  • 这个关系中的函数依赖关系为:
    {Sno, Cname} -> {Sname, Sdept, Mname, Grade}
  • 其中每个非主属性只是部分依赖于键码如Sname只依赖于Sno,因此不符合2NF
  • 可以通过分解的方法使其满足2NF
  • 关系可以分解为

Sno -> Sname, Sdept,Mname
Sno, Cname-> Grade

  • 此时每个非主属性就完全依赖于键码了,满足2NF

3.3 3NF

  • 非主属性中禁止传递函数依赖
  • 在2NF的例子中

Sno -> Sname, Sdept,Mname

  • 而实际上,Mname是依赖于Sdept
  • 因此存在传递函数依赖

Sno -> Sdept -> Mname

  • 可以分解为

Sno -> Sname, Sdept
Sdept -> Mname

  • 这样即满足3NF

ER图

假设教学管理规定:
一个学生可选修多门课,一门课有若干学生选修;
一个教师可讲授多门课,一门课只有一个教师讲授;
一个学生选修一门课,仅有一个成绩。
学生的属性有学号、学生姓名;教师的属性有教师编号,教师姓名;课程的属性有课程号、课程名。

要求:根据上述语义画出ER 图,要求在图中画出实体的属性并注明联系的类型。

【数据库】(1)数据库系统原理_第8张图片

你可能感兴趣的:(数据库)