理解UND0-2 事务

我们从上篇 理解UNDO-1
当中了解到 事务必须先到UNDO表空间里搞定个事务ID 才能开始干活.
拿到了事务ID编号,同时拿到了一块UNDO块来保留旧数据,就可以向目标数据块ITL槽申请位置. 这样我们有一些对像来协调工作了.它们就是
1 UNDO 段块中的事务表
2 UNDO 块里面,旧数据记录
3 数据块 上面的ITL
4 数据块的 ROW

先看第一个,段头块回顾图

事务表的段信息如下

index:标识事务表中的行
state:表示事务状态 9代表非活跃,10代表活跃;
cflags:表示事务状态:0x0无事务;0x10死事务;0x80活动事务;0x90回滚事务;
wrap#:事务槽使用次数
uel:当事务活动时,指向下个可用的事务槽(不重要)
scn:事务开始SCN,或者提交SCN
dba: 事务最后使用的undo块地址
nub:使用多少个UNDO块
cmt:提交时间(不重要)

从这些字段可以大概了解下,有些什么功能,无非是为了回滚准备着. SCN+DBA+NUB 这三个字段就能获得回滚开始地方和结束的地方.
事务拿到事务XID后,这个XID前面说过由UNDO段号,+Index,+wrap# 这三个组成.

事务拿到了XID后, 它执行个UPDATE TABLE SET NAME=’ZFK’ WHERE ID=9;这样的工作, 假如这语句 要更新10笔记录,当这10笔记录分布在5个块中,假设每个块,这里是指数据块,包含15笔记录.目标10笔记录很均匀分布下去,其中有两笔需要更新的.
事务不是一口气把5个块一起修改的,虽然做为人类看是这样的,实际上它先要拿到第一个数据块来修改,修改好了,依次逐渐去修改其他块中的数据.然后整体提交.

那我们看第三个对象 数据块
下面是数据块的逻辑图

数据块信息

这个图有三部分构成
1 是ITL 事务槽
2 是行记录
3 行结构和数据

当事务拿到了事务XID,就要向数据块上的ITL申请,申请到了就把XID放进对应的位置上.
数据块的ITL字段信息
ITL:事务槽号;
XID:事务ID;
UBA: undo块里面的undo记录地址
FLAG:事务当前状态 —-活动;U 快速提交; C 提交并清除;B T 不重要状态;
LCK 锁定行数
SCN/FSC SCN 提交的SCN; FSC 空闲空间审计(不重要)

2 行记录 当中的 pri[0] offset=0x1f85 表示行号和偏移量, 这些值可以在下面的行结构和值中找到

1 行结构和数据
tab 0 ,row 2,@0x1f85
tl:9, fb:–H-FL– Ib:0x1 cc:2
col 0: [2] c1 04
col 1: [2] c1 64

其中 row 2 @0x1f85 对应行记录中的数据; COL 0 表示第一个字段 [2] 表示该字段实际长度; 后面的 C1 04 表示实际的数据.
最重要的是 lb:0x1 表示指向数据块中的事务槽号.

当事务申请到了事务槽号后,通过行记录(目录)(索引项) 找到了目标行,更改LB指针,指向自己的事务槽号.
然后把行当中的某列的值和当前事务槽原来的事务信息. 因为事务槽也会被重用,一起打包保留到UNDO块中.

最后该轮到主角上场啦!! 压轴戏 先看逻辑图

它同样有三个区域
1控制区
2 记录索引区
3 记录区

下面是块的内容: 重点不是要看懂

第一部分 控制区 UNDO BLK:
第二部分: REC OFFSET
第三部分: *———————————

第一部分 XID 就知道该块归哪个事务拥有
第二部分 讲的是UNDO记录和偏移量
第三部分才是重点 又细分三个部分
第1小部分 从— 到—– 算主要是讲事务槽和上个记录
stl 表示该记录是哪个UNDO事务槽号的. 这跟数据块中的行指针 LB 一样的.
opc 表示操作类型
rci 表示上个记录的本块行号
rdba 表示 上个记录的UNDO块地址 外加 irb信息
第2小部分 从*—- 到col 这里主要记录数块中的ITL信息
itli:数据块事务槽号
uba:数据块事务槽号中的uba
第3小部分 就是剩下的 COL 旧数据啦

这样我们就把旧数据安全保存在UNDO块中了.

假设我们已经把5个块,10个目标行修改完后,发出COMMIT命令,这个事务就结束了.那么这5个块上的事务标志FLAGS 都表示C; 另外有个情况是前3个快被DBWR写入了磁盘,为了性能,不能从磁盘再读取出来,做个事务清除工作.留到日后别的事务或者是查询再读取的时候,顺便做一下.

假如 我们修改了前3个块,人工发出ROLLBACK,或者断电进行实列恢复,或者回话被KILL掉了. 我们就要撤销该事务的更新,也就是做回滚操作.

回滚操作:
1 通过UNDO段头上的事务表信息,找到死的事务
2 找到该事务的最后一个块DBA字段 UNDO 记录 跟 数据块UBA一样.
3 到了UNDO块里,读取该记录 恢复 记录当中的旧数据和旧的ITL信息到数据块中
4 然后读取UNDO记录当中的 RCI RDBA IRB等指针信息 找到事务上一条UNDO记录.

这样就完成了回滚链条 可以想象 这是个反向更新操作, 同样资源的消耗,修改数据块,写日志.

读一致性:
1 找到目标行,发现行中的IB 指向的ITL 中的SCN 比自己的大
2 把当前块复制到内存其他区域中
3 对所有提交的事务做清除工,反向更改未提交的事务. (其实就是做块恢复操作)
4 通过行指针指向的ITL中的UBA 找到UNDO块中的记录信息
5 把UNDO块中的记录 旧数据和旧的ITL还原回来
6 再对比还原回来的旧ITL中的SCN,还大的话 继续读取UBA的指针,又去读UNDO块中的记录.重复循环,直到恢复所需要的SCN跟自己一样的

这样就恢复一个独特的数据块出来,属于该回话私有的. 这就是CR块!

这样 UNDO块中的旧记录 通过两个指针完成 回滚和读一致性!

ORA-01555 快照过旧 意思说 读一致性的循环查找 UBA 所指向的UNDO块记录 已经不存在了.被覆盖了! 好比说 你的一个查询 从早上9点中查到下午5点钟,跑了8个小时.当最后这个块在这8个小时中被修改了1千次. 就产生 ITL->UBA->ITL->UBA 这样的1000个链条.
可惜的是这个链条前面最初10点的UNDO块已经超过了900秒,并且UNDO段已经没有空闲UNDO块了,这样它不可避免的被其他事务所征用了. 自然你的查询,当查到该块的时候,已经无法恢复到9点的数据了.
请关注公众号:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值