数据库基础(三)-- 规范化设计
关系模式的设计问题
关系模式的冗余和异常问题
- 数据冗余:同一个数据在系统中多次出现。
- 操作异常:由于数据冗余,在堆数据操作时会引起各种异常。
- 修改异常:当数据冗余时,对某个元组进行修改时,必须所有的相同元组都要修改,如果有一个没有修改就会导致数据不一致。
- 插入异常:如果某个重复的元组当前没有值的时候,对其进行插入,会产生空值,数据库对空值的语义非常复杂,对待空的元组的检索和操作也十分麻烦。
- 删除异常:由于数据冗余,需要对所有重复元组进行删除,这种操作非常不合理。
关系模式的范式
平凡的FD集:对于FD X->Y,如果Y ⊆ X,那么称 X -> Y 是平凡的FD,否则是非平凡的FD。
-
第一范式:如果关系模式R的每个关系r的属性值都是不可分的原子值,那么称R是第一范式。
-
第二范式:如果关系模式R是第一范式,且每个非主属性完全函数依赖于候选键,那么称R是第二范式。(消除部分局部函数依赖)
-
第三范式:属性不依赖于其他非主属性(消除传递依赖)
-
BC范式:设F是关系R的FD集,如果对F中每一个非平凡的FD X->Y,都有X是R的超键,那么称R是BC范式。
(每个属性不传递依赖于R的候选键,每个表只有一个候选键)
-
第四范式:设D是关系模式R上成立的FD 和 MVD 集合,如果D中每个非平凡MVD X—>—>Y的左部都是R的超键,则R是第四范式。(消除多值依赖)
模式设计方法的原则
- 消除异常。
- 信息的可恢复性。
- 保持函数依赖。
数据库管理
事务的ACID性质
- 原子性(Atomic):一个事务对数据库的所有操作,是一个不可分割的工作单元。这些操作要么全部执行,要么什么也不做。
- 一致性(Consistency):一个事务独立执行的结果,应保持数据库的一致性,即数据不会因事务的执行而遭受破坏。
- 隔离性(Isolation):在多个事务并发执行时,系统应保证与这些事务先后单独执行时结果一样。
- 持久性(Durability):一个事务一旦完成全部操作以后,它对数据库的所有更新应永远地反映在数据库中,不会丢失。
数据库的并发控制
- 丢失更新问题:两次事务先后执行,但是其中一个事务的结果未保存就进行了下一个事务的操作,导致数据丢失。
- 读脏数据:事务一读取了事务二的未提交数据。未提交的随后被撤销的数据成为脏数据。
- 不一致分析:当某一个事务还未执行完毕,被另一个事务接着执行导致数据不一致。
解决并发控制问题—封锁机制
- 排它型封锁(X锁):当事务对某个数据实现 X 锁,那么其他事务必须等该事务处理完毕才可以进行。
- 共享型锁(S锁):如果事务对某个数据加上 S 锁,仍允许其他事务再对数据进行加 S 锁,但是对数据的所有 S 锁都解除之前绝不允许任何事务对数据加 X 锁。
活锁,饿死和死锁
-
活锁:系统可能使某个事务永远处于等待状态,得不到封锁的机会,这种现象称为活锁。
解决活锁:先来先服务,如果某个事务因优先级低而得不到执行,那么当事务等待若
干时间以后,则对事务的优先级进行升级以达到执行。
-
饿死:有可能存在一个事务序列,里面的每一个事务都申请对某数据加 S 锁,且每个事务在授权后的一小段时
间内释放封锁,此时若另有一个事务T1欲在该数据项上加 X 锁,即永远轮不上封锁的机会,这种现象
称为饿死。
解决饿死:当事务 T 对数据 Q 加 S 锁的条件是:
- 不存在数据项 Q 上有其他持有X锁的事务。
- 不存在等待对数据项 Q 加锁且先于T申请加锁的事务。
-
死锁:系统存在两个或者两个以上的事务都处于等待状态,并且每个事务都在等待其中一个事务解除封锁,他
才能继续执行下去,如果造成任何一个事务都无法继续执行,这种现象称为死锁。
可以使用事务依赖图测试系统中的死锁。
解决死锁:DBMS有一个测试死锁的程序,每隔一段时间就会检查并发事务之间是否发生死锁,如果发生死锁,那么只能抽取某个事务作为牺牲品,把它撤销,做回退操作,解除它的所有封锁,恢复到该事务的初始状态。释放出来的资源就分配给其他事务,使其他事务有可能继续执行下去,这样就可以消除死锁。