一、事务
-
事务是数据库恢复与并发控制的基本单元
-
什么是事务结束的象征:数据已经持久化到硬盘中(提交成功后)
事务的四大特性:ACID
-
原子性:由于事务是对一个或一组的DML操作的封装,同时也相当与是一个业务,因此不可再分,保证了事务是数据库恢复与并发控制的基本单元。
-
一致性:为确保数据库在事务被执行时非法中断后,保证事务未提交前的数据不变性,因此在未提交前数据库并没有把事务的DML操作的数据持久化到硬盘
-
隔离性:事务的隔离性是解决多个事务并发执行的问题,其中有4个隔离级别
-
读未提交(read uncommitted),在当前事务执行时,它能读取其他事务中未提交的数据。
出现的问题:脏读;脏数据:未持久化到硬盘的数据或者说原本该数据状态被持久化到数据库,但其他事务又将这个数据更新了
-
读已提交(read committed),在当前事务执行时,它不能读取其他事务中未提交的数据。
解决了脏读问题,但是也带来了不可重复读
什么是不可重复读:当前事务不能读到事务开始时刻的数据状态(由于其他事务的执行一直在修改硬盘中的数据)。
什么是可重复读:事务的开启,说明使用了一个线程执行,那么这个线程会对数据库存下一个副本(快照),在这个事务执行的整个过程中读取到的数据都是这个副本,因此读到的数据是一致的。
-
可重复读 (read repeated)
解决了不可重复读,但是带来了幻读,读取到是数据可以说是一个幻象(非实践存储的数据)
-
可序列化读(read serializated)
开启最厚的隔离墙,直接不允许多事务并发执行,也就是期望并发的事务所在的线程加锁,使之同步
-
持久性:在事务成功提交了之后,数据的最终变更操作都会持久化到磁盘上去,不会因为故障导致数据丢失
二、索引
2.1 什么是索引?
索引是对查询的一种优化,缩小查询范围,防止不必要的全表扫描
2.2 创建索引的时机
-
数据量非常大
-
对该字段的修改少,即少DML操作
-
该字段出现在where语句的次数非常多
2.3 如何创建索引?
-
手动创建/删除:create/drop index 索引名 on 表名(字段名)
-
自动创建:主键或unique约束
2.4 索引的底层原理?
数据库会在磁盘或内存中创建索引对象,这个索引对象的数据结构底层是B+树,索引对象中的每一数据象征着一个元组的物理地址,可直接通过该物理地址直接定位到该元组,而无需进行全表扫描
select * from student where sid = 2222;
转换为
select * from student where 物理地址 = 0x...;
2.5 索引的分类?
-
单一索引:单个字段作为索引
-
复合索引:联合字段作索引
-
主键索引:primary key
-
唯一索引: unique
2.6 什么时候索引失效?
当使用模糊查询时,且查询条件第一个字符是通配符&
三、恢复技术
3.1 事务内部故障
-
可预期的:即在程序逻辑上可预判的错误,这可通过条件判断是否对事务的提交或者回滚
-
不可预期的:如运算溢出、死锁等,无法在程序可预料到的,事务没有到达预期的终点,数据库中数据状态处于非正确的状态,这样不可预期的事务故障需要撤销,即UNDO 操作,撤销该事务对数据库做的任何修改。
3.2 系统故障
数据库系统异常宕机或者是设备断电,导致内存中事务对数据的修改的丢失
因系统故障的恢复需要重做异常中断的事务(REDO)
登记日志文件
以记录为基本单位的日志文件
需要记录的内容:
-
各个事务的开始标记(BEGIN TRANSACTION)
-
各个事务的结束标记(commit/ rollback)
-
各个事务的所有更新操作
这些都作为日志文件的一个日志记录(log record)
log record的内容:
-
事务标识(表明是哪一个事务)
-
操作类型(增删改)
-
数据的旧值(插入操作旧值为null)
-
数据的新值(删除操作新值为null)
以数据块为基本单位的日志文件
记录内容:
事务标识、被更新的数据块
日志文件的作用
-
用于事务故障和系统故障的恢复,并协助后备副本进行介质故障恢复
-
事务和系统故障的恢复必须使用日志文件
-
在动态转储方式中必须建立日志文件,后备副本和日志文件结合才能有效恢复数据库
-
在静态转储方式中也可建立日志文件,利用日志文件把已完成的事务REDO,把故障时未完成的事务UNDO
日志文件规则
-
登记的次序严格按照事务并发执行的顺序,不能颠倒
-
先做日志,再写数据库
3.3 事务故障恢复
-
反向扫描日志文件(从后往前),找到该事务的更新操作
-
对该事务的更新操作执行逆操作,将更新前的值写入数据库
-
重复上一操作,直到该事务的开始标记 BEGIN TRANSACTION
3.4 系统操作恢复
系统故障造成数据库数据不一致的原因
-
未完成的事务对数据库的更新可能已经写入了数据库(持久化到硬盘)
-
已提交的事务对数据库的更新可能还留在缓冲未写入数据库
方案:
-
UNDO未完成的事务
-
REDO已提交的事务
四、并发控制
4.1 并发控制机制的任务
-
保证并发事务调度的正确性
-
保证事务的隔离性
-
保证数据库的一致性
4.2 并发操作对数据的不一致性:
-
丢失修改
-
脏读
-
不可重复读
并发事务导致数据的不一致性的原因是并发事务的操作破坏了事务的隔离性,并发控制就是通过正确的方式调度并发操作,使用一个事务时不被其他事务干扰,破坏数据的不一致性
4.3 封锁
什么是封锁?
封锁就是事务T对某个数据对象操作之前,先向系统发出请求对其加锁,加锁之后事务T就对该数据对象(表、记录等)有一定的控制(不允许其他事务对该数据对象的更新操作),在事务T释放该锁之前,其他事务无法对该数据对象进行更新操作
4.4 基本锁类型
-
排它锁(写锁) Exclusive Locks 也叫X锁,指只允许事务T对该数据对象的读写操作,拒绝其他事务对该数据对象的任何操作,直到事务T释放X锁
-
共享锁(读锁) Share Locks 也加S锁,指只允许某事务对该数据对象的读操作,也只允许其他事务对该数据对象加S锁或读操作,不能加X锁,直到锁释放
锁的相容矩阵
-
某事务对一数据对象的X锁与其他任何事务在该数据对象的任何锁不相容,但相容无操作的事务
-
某事务对一数据对象的S锁与其他任何事务在该数据对象的X锁不相容,但相容S锁和无操作的事务
4.5 封锁协议
封锁协议决定了什么时候加锁、加什么锁、什么时候释放锁
三级封锁协议
一级封锁协议
-
指在事务T在对某个数据对象更新操作之前,对该数据对象加X锁,直到该事务结束之后即事务正常结束commit或事务非正常结束rollback,才释放X锁
-
一级协议解决了事务并发对数据的丢失修改
二级封锁协议
-
在一级封锁协议的基础上,其他事务对该数据对象读操作之前,加S锁,但是读完立即释放S锁
-
二级协议解决了丢失修改和脏读问题
三级封锁协议
-
在一级封锁协议的基础上,其他事务对该数据对象读操作之前,加S锁,但是是等事务结束才释放S锁
-
三协议解决了丢失修改、读问题和不可重复读问题