事务
属于一种数据库恢复技术,用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是不可分割的工作单位
Why
事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位(不可再进行分割),由一个有限的数据库操作序列构成(多个 DML 语句,select 语句不包含事务),要不全部成功,要不全部不成功。
A 给 B 要划钱,A 的账户 -1000 元, B 的账户就要 +1000 元,这两个 update 语句必须作为一个整体来执行,不然 A 扣钱了,B 没有加钱这种情况就是错误的。那么事务就可以保证 A 、B 账户的变动要么全部一起发生,要么全部一起不发生。
How
通常以 BEGIN TRANSACTION
开始,以 COMMIT/ROLLBACK
结束.
COMMIT
表示提交,提交事务的所有操作ROLLBACK
表示回滚,即在事务运行过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态
What
故障的种类及恢复策略- 事务故障
- 反向扫描文件日志,查找该事务的更新操作
- 对该事务的更新操作执行逆操作
- 继续反向扫描日志文件,做同样处理
- 如此处理下去,直至读到此事务的开始标记,该事务故障的恢复就完成了
- 系统故障 (软故障)
- 正向扫描日志文件,找出在故障发生前已经提交的事务队列和未完成的事务队列
- 对撤销队列中的各个事务进行撤销处理
- 对重做队列中的各个事务进行重做处理
- 介质故障 (硬) : 最严重的一种故障. 恢复方法是重装数据库,然后重做已完成的事务.
- 装入最新的数据库后备副本 (离故障发生时刻最近的转储副本) , 使数据库恢复到转储时的一致性状态
- 装入转储结束时刻的日志文件副本,重做已完成的事务.
- 计算机病毒
- 事务故障
- 特性 (ACID, A、I、D 是手段; C 是目的)
- Atomicity,原子性
- 将所有 SQL 作为原子工作单元执行,要么全部成功,要么全部失败,不能只执行其中的一部分操作
- 如果原子性不能保证,就会很自然的出现一致性问题
- Consistency,一致性
- 事务完成后,所有数据的状态都是一致的
- 即 A 账户只要减去了 100,B 账户则必定加上了 100
- 一致性
- 事务完成后,所有数据的状态都是一致的
- Isolation,隔离性
- 如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离
- Durability,持久性
- 事务完成后,对数据库数据的修改被持久化存储
- Atomicity,原子性
数据库恢复的基本技术 → 恢复到故障前某个一致性状态
- 建立冗余数据最常用的技术
- 数据转储
- 登记日志文件
- 检查点记录是一类新的日志记录.
- 建立检查点时刻所有正在执行的事务清单
- 这些事务的最近一个日志记录的地址
事务隔离级别
定义了数据库系统中一个事务中操作的结果在何时以何种方式对其他并发事务操作可见,via: https://en.wikipedia.org/wiki/Isolation_(database_systems)
- 读取未提交 (READ-UNCOMMITTED)
- 最低的隔离级别
- 允许读取尚未提交的数据变更
- 可能会导致脏读、幻读或不可重复读
- 读取已提交 (READ-COMMITTED)
- 允许读取并发事务已经提交的数据
- 可以阻止脏读,但是幻读或不可重复读仍有可能发生
- 可重复读 (REPEATABLE-READ)
- 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改
- 可以阻止脏读和不可重复读,但幻读仍有可能发生
- 可串行化 (SERIALIZABLE)
- 最高的隔离级别, 完全服从 ACID 的隔离级别
- 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰
- 该级别可以防止脏读、不可重复读以及幻读
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读取未提交 | √ | √ | √ |
读取已提交 | × | √ | √ |
可重复读 | × | × | √ |
可串行化 | × | × | × |
并发 带来的数据的不一致问题
- 脏读 (Dirty read)
- 丢失修改 (Lost to modify)
- 不可重复读 (Unrepeatable read)
- 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样
- 幻读 (Phantom read)
- 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样
- 不可重复读 vs 幻读
- 幻读是不可重复读的一种特殊情况
- 不可重复读的重点是内容修改或者记录减少
- 幻读在于记录新增
- 幻读是不可重复读的一种特殊情况
避免死锁的简单方法是采用先来先服务的策略
三级封锁协议
- 一级封锁协议
- 写数据前加写锁,读数据不加锁. 只能防止丢失修改.
- 二级封锁协议
- 在一级封锁协议上,读取数据需要加读锁,读完就释放. 避免读脏数据.
- 三级封锁协议
- 一级封锁协议上,读数据加读锁,事务结束再释放.