Oracle学习笔记 读一致性(ORA-01555错误机制分析)及Undo表空间大小设置
Posted 新站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle学习笔记 读一致性(ORA-01555错误机制分析)及Undo表空间大小设置相关的知识,希望对你有一定的参考价值。
Oracle 学习笔记 读一致性(ORA-01555错误机制分析)及Undo表空间大小设置
这节课我们把和undo相关的另外一个技术、另外一个细节读一致性再深入地讲一下
一)一致性读和事务
一个事务开始以后
分配undo段头事务表和undo块
事务表指向undo块
数据块中有事务槽,底下有数据行
数据块事务槽中事务id指向事务表
事务表指向undo块
数据块事务槽也指向undo块
修改数据块中的数据行
修改的时候有指向关系
数据行指向数据行对应事务槽
A事务修改数据行以后
这个数据行指向数据块的A事务的事务槽
事务槽中有事务信息也有回滚块信息
回滚块信息指向undo块
事务信息指向undo段头的事务表
B会话访问同一数据行
发现这个数据行有锁定标记
就是数据行有一个数据指向事务槽
在行发现有链指向事务槽说明这个事务没有提交
这时不能读
B就构造一个cr块
这个cr块里面
没有修改的数据行写上
修改的数据行
根据锁定标记找事务槽
根据事务槽uba信息找undo块
undo块中把这一行找出来
把修改前的数据找出来写到cr块中
构造出来一个cr块
然后B读这个cr块
cr块中有一行是从undo块中读的
是事务提交前的信息,也就是说是事务修改前的信息
通过刚才我讲的技术oracle避免了脏读
一个会话读到了另外一个会话未提交的事务所修改的数据叫脏读
oracle保证你读的数据永远是提交后的数据,未提交的数据你不会读到
读一致性里面最简单的oracle通过回滚数据避免了脏读
二)一致性读的事务实现
1)一个例子
再来往深里研究一下
我们有这么一个需求
oracle读一个表这个表很大比如说一万行
当然实际中10000行很小了
假设十万行一百万行,咱们就说一万行
oracle要读一个表10000行
假设这个过程的时间拉长了
8:50开始读这个表,这个表有一万行
8:55的时候这个表的最后一行被删了被提交了
9:00的时候oracle读完这个表了
按照刚才那个分析应该是读9999行
因为读到最后一个块的时候块里面的所有的行的所对应的事务已经提交
它应该会直接读出来9999行
其实oracle会读出一万行来
这也是读一致性的要求
我们可以这么认为
oracle要读一个表的时候
首先对这个表做一个快照
快照就像照一个像
接着从头读到尾
读的是静止的状态
oracle 8:50读这个表的时候
啪给这个表照一个像
照的是8:50的时刻然后接着就开始读
从头到尾读表的所有的行都是8:50那一时刻的这个数据
这个时候应该是对的
也就是我们读的是1万行
oracle希望是这样
给大家分析一下oracle如何来实现的
这里面有几个关键技术
2)scn时间点
oracle在8:50开始读这个表的时候
也就是开始执行这个select语句的时候
oracle把时间点记下来
就是SCN850,假设scn是这样的,我们用一个字符串来表示更好一些
8:50的时候执行了select这时候它把这个时间点记下来scn850
假如我8:50的时候突然时间静止了
这个时候我敢保证目前所有的数据块,或者说目前我要读的所有的数据块
它里面的事务槽的scn都小于8:50
也就是好像
我这个屋子
现在8:50我突然让时间静止8:50
这个屋子里面所有的东西都是8:50以前生产的
不可能现在8:50了
这个屋子你找出一个东西来它是9:00生产的
那不现实
现在是记住了scn8:50或scn850
现在保证
oracle接下来读的在8:50这个时间点
oracle要读的这个表的所有的数据块的事务槽里的scn都小于850或小于等于850
有了这个做基础了
select语句执行的时候先把时间点记下来
3)事务产生redo和undo
我们先来分析这个事务
一个事务开始了,
开始的时候事务表加上一行信息
假设有两个回滚块,回滚块之间有链接指向
事务表中的这行指向该事务的最新回滚块
这个事务有可能修改很多数据块
数据块中有事务槽
事务槽指向事务表
数据块事务槽中的uba地址指向回滚块
在这个事务的整个的执行过程中
先是事务表
再就是回滚块、事务槽、数据行
数据行修改了指向数据块对应的事务槽
从数据行到事务槽
从事务槽到回滚块
从事务槽再到事务表
事务表再一步步到回滚块
这整个的形成一个链状
在这个过程中有几个关键点
第一、
在这个事务所修改的所有的地方都产生redo
修改了事务表、回滚块、事务槽、数据行
修改的这四个地方全部产生redo
第二、
对数据块的所有的修改全部产生undo
包括事务槽
也就是当我要覆盖一个事务槽的时候
我一定会做一件事情
把原来事务槽的信息也放到undo块里面去
第一都产生redo
第二对数据块的所有的修改全部产生undo
第二个数据块同样
4)事务槽的覆盖
引申一下假设现在对这个数据块来讲
8:50的时候我们找到这个数据块
这个时候这个数据块的里面的scn是scn840
因为这个数据块在8:40的时候做过修改同时提交了
在8:50这个时刻这个数据块事务槽是scn840
数据块被修改首先来讲会产生事务表、回滚块
因为一个新的事务重新分配事务表重新分配回滚块,和原来的没关系
修改的时候
因为上个事务槽被修改了已经提交了
可以覆盖了
数据行因为提交了也可以被修改
这时候第二个事务8:55的时候要修改这个数据块
先把事务表以及回滚块给准备好了
接着要修改数据块
要修改的数据块除了redo都产生以外
这个数据块修改的包括事务槽以及包括这个数据行都要被undo
这时候这个事务槽信息和数据行信息都被写到回滚块里面去
这里面各个事务信息的链就会发生变化
数据块的事务槽数据
新事务槽产生覆盖了原来的事务槽
被覆盖的事务槽被写到undo块
undo块中的老事务槽也有指向
仍有指向undo段头事务表
原来事务槽位置中新的事务槽原来对undo块的指向去掉了
老的事务槽现在在undo块中的事务槽
仍是原来的指向,指向它原来的undo块
因为原来的数据块的这些信息这个事务槽信息和数据行信息
都被移走了移到undo块里面去
自然地址也被移走了
出现了在undo块中备份的事务槽的这种指向的情况
数据块产生新的事务槽
自然指向新的事务
这个事务指向最新的undo块
但这时undo块中有原来的事务槽的备份
这时候新的事务槽scn是855了,scn855
这个新的数据块中的事务槽还指向最新的这个事务的undo块回滚块
5)事务cr读结果
8:50开始的查询
当9点钟的时候要读这个数据块
读的时候发现这个块的事务槽的scn是855
显然大于850
它就确认这个块在8:50以后做过修改
既然做过了修改
我要找8:50以前的数据就要构造cr块
cr块显然是数据块里面的数据行加上undo数据
根据事务槽找到事务再找到undo块
把事务槽和数据行拿回来
在cr块里写入事务槽、数据行,构成一个cr块
undo块拿出来的事务槽
这个事务槽里面的scn是840
构造出的cr块里面的事务槽里面的scn是840
840显然小于850
小于850的话cr块可用
这一行数据读出来了
这就是读出一万行的一个原理所在
三)事务的递归回滚
对一个数据块来讲
根据事务槽找到这个事务
根据这个事务我再找回滚信息
在回滚信息里面还可以找到更老的一个事务槽
更老的事务槽又对应着相应的事务
事务又找回滚
又可以找到回滚数据
在回滚数据里面又对应着一个更更老的一个事务槽
再往前走,还可以一直再往前走
通过这个我们可以看到一个知识点
可以这么认为
一个当前的数据块
根据回滚信息可以一直往前找
在undo数据保留时间足够长的情况下
可以找到对这个数据块所做的所有的修改过的一些回滚数据
这个数据块现在是9:00
我可以找到8:55的这个数据块的状态
如果undo数据有的话
可以找到8:40的、8:30的、8:20的、昨天的、前天的、大前天的
甚至上个月的
如果undo表空间里的数据足够多的话
我从当前的数据块以当前的数据块为起点
沿着undo数据一直找、找、找的话
可以找到最早的对这个数据块修改的所用的事务以及回滚数据
也就是说这个数据块此前的所有的undo数据是以链状的形式串起来的
原理就是因为一个数据块
我记录undo数据的时候
不仅仅记录修改的数据行,事务槽也被记录了
到目前为止记住一句话就可以了
一个数据块,根据这个数据块的undo数据
一直往前找,一直往前找,可以找到足够早的这个数据块的一个回滚数据
比如说先前的数据块是9:00
我可以通过当前块找到数据块9:00的状态
还可以根据undo数据找到8:50的
再往前找到8:40的,再往前找8:30的、8:20的、8点10分、8点5分甚至7点
可以一直往前找
因为undo数据时串在一起的
当然前提是undo数据足够长足够大,undo表空间足够大
四)ORA-01555错误
再看一个例子
8:50的时候开始读这个表读这个数据块
记下这个时间点
在8:51的时候,这个表的最后一行被删了被提交了
8:52的时候这个数据块又被删了一行然后又被提交了
8:53的时候这个数据块又被删了一行又被提交了
8:55的时候我读这个数据块的时候
我发现这个数据块里面事务槽的scn号是8:53
8:53显然大于8:50,我需要往前构造cr块
第一步把8:53的回滚了构造出8:52的
8:52不满足,我再构造构造8:51的
还不满足,再构造,构造8:40的
ok!小于8:50了
这时候这个cr块构造出来了可以读了
有可能出现这种情况
事务在8:50开始在8:55读到这个块的时候
往前构造
构造出8:53的没问题,因为这个事务刚发生的
8:52也构造出来了
但是8:52构造出来后再往前构造的时候没有了
因为8:51这个事务提交的时间比较早了
它的undo数据有可能被覆盖,8:51的数据没有了
也就是我要读这个数据块的时候
我构造cr块最早能够构造到8:52
这个时候oracle就会报错
报一个:snapshot too old
就是很经典的ORA-01555错误
就是需要构造出来的快照的时间点太老了,已经没法构造出来了
原因是:
第一、这个sql语句,这个select执行时间太长
第二、undo表空间压力很大,导致你的undo数据被覆盖
第一、如果你的select语句时间很短两秒钟就执行完了
可能就没有我刚才的问题
第二、如果你的undo表空间压力不大
这个时候它优先会使用free和expired这些区
你的8:51的数据可能会一直存在,可能7点的6点的数据都存在
不会出现snapshot too old
所以说oracle的01555错误产生原因有两个
第一个sql语句的执行时间过长
第二个undo表空间的空间压力很大,undo表空间的undo数据保存时间过短
对第一个问题我们往往没办法解决
因为你的执行时间不好控制,确实执行一个长select语句
但是我们可以增加undo表空间来缓解这个错误
这就是snapshot too old机制
就是01555错误原因
五)设置undo表空间大小
undo表空间大小怎么来设置
通过EM来看一下
进入EM
在EM主页的相关链接有一个 指导中心 链接
进入指导中心页
在 指导 部分有 还原管理 链接
进入 还原管理 页
建议案 部分 有以下的一个部分
系统活动和表空间使用情况
此建议案基于所选分析时段的系统活动和还原表空间使用情况。
运行时间最长的查询 (秒) 0.0
平均还原生成速率 (KB/分钟) 56.0
最大还原生成速率 (KB/分钟) 548.0
列出了
运行时间最长的查询
还有undo的生成速度每分钟是多少的统计信息
01555错误
第一个和undo表空间的空间压力就是undo数据生成速度有关
再就是指令运行时间有关
知道这两个参数以后
oracle就可以确定你undo段该设多大了
接着点击
还原管理 页 中的 还原指导 按钮
进入 还原指导 页
有一个图 说明 还原保留时间所需的表空间大小
横坐标:还原保留时间(分钟)
代表着要undo数据保留多长时间
纵坐标:所需表空间大小(MB)
是在系统当前负载的情况下
你要保留undo数据一定长的时间就需要对应大的空间
有了横坐标以后纵坐标自然就有了
横坐标表示你要保留多长时间
我们要保留的时间至少应该大于最长的sql语句执行的时间
比如最长的sql语句执行时间是10分钟
这时候我就找到10分钟横坐标这个点
对应着找undo空间需要多大
但在实际的工作中
undo保留的时间
除了我们要考虑最长的sql语句以外
还要考虑比如说将来的闪回
我有可能今天突然想把昨天的数据闪回来
就是闪回到昨天
这个时候需要保留的时间更长一些
也就是说
你首先要确定数据库这个undo保留时间到底希望是多少
这个考虑因素不仅仅是最长sql语句了还有一些别的内容
确定好时间以后
自动对照图表找这个undo空间大小就ok了
举例讲有时候我们希望保留24小时或保留一个月的undo数据
都是有可能的
图的横坐标单位是分钟
把时间化为分钟以后
从图中对应着找大小就ok了
这就是我们这个图表的使用
关于undo的一些信息后面还会陆陆续续提到
总之undo该设多大
就是根据时间找大小
这个时间到底是多少,根据业务需求去定
至少应该大于最长sql语句的执行时间
这是EM中关于undo表空间大小的设置
六)和undo相关的sql语句
查看回滚段的使用情况,哪个用户正在使用回滚段的资源
select s.username, u.name from v$transaction t,v$rollstat r,
v$rollname u,v$session s where s.taddr=t.addr and
t.xidusn=r.usn and r.usn=u.usn order by s.username;
通过这个可以知道各个回滚段的负载情况
检查UNDO Segment状态
select usn,xacts,rssize/1024/1024/1024,hwmsize/1024/1024/1024,shrinks
from v$rollstat order by rssize;
xacts是事务数量等等一些信息
还有一些内容在以后讲优化的课程的时候再给补上
这个地方只是讲了oracle的undo的一些原理知识以及undo的设置
2017年8月28日
文字:韵筝
以上是关于Oracle学习笔记 读一致性(ORA-01555错误机制分析)及Undo表空间大小设置的主要内容,如果未能解决你的问题,请参考以下文章