【DBA及开发必备】全解ORA-1555快照太旧错误原理及解决方案

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

不论你的工作是管理Oracle数据库,还是开发、维护Oracle上的应用程序,通常来讲你都遇到过ORA-01555:snapshot too old这样的错误。本文为你详解错误产生的原因以及最佳解决方案。 

ORA-01555产生的过程

 


我们先来看看ORA-01555是怎样产生的:


20160329064534658.jpg


错误记录在哪?

 


通常,这个错误可能会在以下文件中出现:


1  Alert 告警日志文件 


报错信息类似:


ORA-01555: snapshot too old: rollback segment number 107 with name "_SYSSMU107_1253191395$" too small


2  问题发生时的跟踪日志文件 


默认情况,ORA-01555错误发生时不会自动生成跟踪日志文件。但是可以在系统里设置下面的事件,让它在错误发生时同时生成:


alter system set events '1555 trace name errorstack level 3';


设置了1555事件后,一旦错误发生,就会生成相应的日志文件,类似如下:


20160329064544340.jpg


错误因何而来?

 


产生ORA-01555错误的根本原因是由于UNDO块被覆盖,查询语句不能获取到查询语句发起时刻所构造的数据副本。


已知的一些原因如下:


1  相应行数据的UNDO记录已经过期了 


这里说的过期是当前时间(指错误发生时)离数据提交时间已经超过UNDO_RETENTION设定的值。一旦已提交的记录对应的UNDO记录是“expired”状态,就表明这部分空间可以重用,数据可以被覆盖了。


你可能会问,为什么有时候我们遇到ORA-01555错误时,查询语句运行时间比UNDO_RETENTION要长很多,有时候却短很多呢?这没什么明确的答案。


要看具体问题发生时UNDO表空间有多忙,系统负载有多大。


提示:一个活动或者未提交的事务对应的UNDO记录会被标记为“ACTIVE”状态。一旦事务被提交,相应的UNDO记录被标记为“UNEXPIRED”,它将持续一段时间(这段时间由UNDO_RETENTION参数决定,如果使用了自动还原段管理,那是由TUNED_UNDORETENTION决定,该参数的值系统自动评估),过了这一时间后,这一UNDO记录被标记为“EXPIRED”,该空间可被重用。


2  相应行数据的UNDO记录状态并非过期,但仍然被覆盖了 


发生这种情况有2个必要条件:


  • 对UNDO表空间没有设置RETENTION GUARANTEE

  • UNDO表空间满了


这个时候,“UNEXPIRED”状态的UNDO记录就可能被覆盖了。


3  LOB段的LOB段的读一致性副本不再可用 


依赖于LOB字段是怎样配置的,in-row还是out-of-row,in-row方式的LOB字段在UNDO表空间中采用跟普通行一样的UNDO算法。


Out-of-row方式的LOB字段不一样,它的读一致性副本有下面2种控制方式


1)老的方式:PCTVERSIOIN


这个参数关系到LOB数据的一致读,指的是表lob字段所在的表空间需要预留给lob的前映象使用的最大百分比,默认值是10。也就是说,只要使用不超过10%,LOB字段的前映像的数据是不会被覆盖的。


2) 新的方式(自动还原段管理使用):RETENTION


Oracle用UNDO_RETENTION参数来决定在数据库中保留多少已经提交的UNDO数据。这种方式LOB段跟普通段使用相同的过期策略。


在这种方式中,用LOB字段的语句发生ORA-1555的话,意味着:


LOB字段的前映像的使用已经超过PCTVERSION,读一致性数据被覆盖。


或者,LOB字段前映像超过了RETENTION的值,在查询发生时一些行的LOB字段前映像已经被覆盖,于是ORA-1555触发。


解决方案

 


1  检查错误日志信息 


通过检查告警日志,或者包含ORA-1555错误信息的跟踪日志,可以更详细的看到具体的错误类型:


1)提示回滚段太小


错误提示:


ORA-01555: snapshot too old: rollback segment number with name "" too small(注意!!!这里的回滚段名字是空的)


或者,


ORA-22924: snapshot too old


这种错误说明是访问的UNDO数据是LOB字段类型。LOB字段访问遇到ORA-1555错误通常是下面几个原因导致的:


  • LOB段损坏


参考MOS文档检查是不是这个问题:


Document 452341.1 ORA-01555 And Other Errors while Exporting Table With LOBs, How To Detect Lob  Corruption


  • 如果没有LOB损坏,检查Retention/Pctversion值是不是合适


参考MOS文档,确认是不是需要调高Retention/Pctversion:


Document 846079.1 LOBs and ORA-01555 troubleshooting


ORA-01555: snapshot too old: rollback segment number 107 with name "_SYSSMU107_1253191395$" too small


注意,这个错误提示跟上面不一样。"_SYSSMU107_1253191395$"表示UNDO数据是在UNDO表空间的。


这个ORA-1555错误报告是在访问UNDO表空间的UNDO数据时发生错误的,用后续的方法来诊断问题。


2)查询耗时太长


在一些ORA-1555错误发生时,会在alert日志或者是应用日志中出现查询失败时耗时(Duration)的秒数:


ORA-01555 caused by SQL statement below (Query Duration=1974 sec, SCN: 0x0002.bc30bcf7):


如果发现错误日志中,duration=0或者耗时很短,查看下面的文档:


Document 1131474.1 ORA-01555 When Max Query Length Is  Less Than Undo Retention, small or 0 Seconds


如果查询耗时超过UNDO_RETENTION值,可以考虑加大UNDO_RETETION,同时要记得调整UNDO表空间大小。


如果查询耗时等于或者接近UNDO_RETENTION,继续看后面的文字。


2  检查UNDO数据文件 


20160329064601753.jpg


如果UNDO数据文件没有关闭自动扩展功能,可能会导致TUNED_UNDORETENTION值被计算得很高,因此UNDO空间分配是偏向于更多的空间。那怎么破呢?使用UNDO数据文件自动扩展功能,即使存储可用空间足够的时候也带上MAXSIZE。


注意:强烈建议,不要让UNDO表空间里同时存在关闭自动扩展功能的UNDO数据文件和打开自动扩展功能的UNDO数据文件,因为这会导致TUNED_UNDORETENTION计算错乱。


3  检查 TUNED_UNDORETENTION 


20160329064607902.jpg


1)TUNED_UNDORETENTION比MAXQUERYLEN小


这种情况表明UNDO表空间有空间上的压力,实际保留的UNDO记录比理论上的要少。


解决办法是扩大UNDO表空间。


2)TUNED_UNDORETENTION比MAXQUERYLEN大很多


通常发生在UNDO表空间的数据文件关闭自动扩展选项的情况下。内部的算法是尽可能久的保持UNDO记录,因此TUNED_RETENTION的值就会比较高。


解决办法是把所有的UNDO数据文件设置为自动扩展,并且加上MAXSIZE选项。


长时间运行的查询语句也会把TUNED_RETENTION的值搞得很高。这种情况。就要优化SQL语句来避免保留过多UNDO数据在UNDO表空间了。


通过下面的语句来识别哪些查询语句耗时较久:


20160329064615887.jpg


3)状态为ACTIVE/UNEXPIRED的UNDO占比很高


20160329064626237.jpg


下面的几种情况可能会产生大量ACTIVE/UNEXPIRED状态的UNDO:


  • UNDO_RETENTION或TUNED_UNDORETENTION值很大

  • 在某个特定时间点产生了大量UNDO数据。用下面的语句诊断:

    20160329064655976.jpg

  • 大量的死事务回滚

  • 使用了闪回数据查询


关于状态为ACTIVE的UNDO的信息,可以参阅:


Document 1337335.1 How To Check the Usage of Active Undo  Segments in AUM


4  UNDO_RETENTION 


建议将UNDO_RETENTION的值至少设置为MAXQUERYLEN的一半。如果发生了ORA-1555错误,则适当调大。


20160329064648280.jpg

到此,基本上涉及ORA-01555错误的原理和诊断就说完了。


如果还有不明白的,请在文章下留言,我们继续探讨。

 

译者:杨志洪

  • 【DBA+社群】联合发起人

  • 数据管理专家。Oracle ACE、OCM、 SHOUG/ZJOUG核心成员、DAMA会员/CCF会员,译著《Oracle核心技术》。

  • 在Oracle OOW、DTCC及2015Oracle数据库技术大会等全国性技术会议上发表主题分享,并主办了2014Oracle全国技术巡讲。

  • 2015年创立DBA+社群迅速成为全中国最大的涵盖数据架构师、DBA及中间件的专业社群。


本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2016-02-24

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
Oracle 关系型数据库 数据库
实战篇:Oracle 数据坏块的 N 种修复方式
实战篇:Oracle 数据坏块的 N 种修复方式
实战篇:Oracle 数据坏块的 N 种修复方式
|
3月前
|
SQL Oracle 容灾
程序与技术分享:DG概念与机制
程序与技术分享:DG概念与机制
|
4月前
|
Oracle 关系型数据库 数据库
oracle 重启步骤及踩坑经验
oracle 重启步骤及踩坑经验
235 0
|
存储 SQL 缓存
数据库小技能:Oracle基础【上篇】
QPS: 请求进入的速度 并发数: 系统中同时存在的请求数 并发数 = QPS * 耗时
187 0
数据库小技能:Oracle基础【上篇】
|
存储 SQL 缓存
OceanBase 源码解读(十二):宏块的垃圾回收和坏块检查
此前,OceanBase 源码解读第十一篇《Location Cache 模块浅析》,为大家介绍了 observer 上的一个基础模块,为 SQL、事务、CLOG 等多个其他模块提供获取及缓存某个副本位置信息的能力的 Location Cache 模块。本期“源码解读”继续由 OceanBase 技术专家公祺为大家带来“存储层代码解读之「宏块的垃圾回收和坏块检查」”。
310 0
OceanBase 源码解读(十二):宏块的垃圾回收和坏块检查
|
运维 Oracle 关系型数据库
实战篇:Oracle DataGuard 出现 GAP 修复完整步骤
实战篇:Oracle DataGuard 出现 GAP 修复完整步骤
实战篇:Oracle DataGuard 出现 GAP 修复完整步骤
|
运维 Oracle 关系型数据库
Oracle运维笔记之ORA-27102错误处理
Oracle运维笔记之ORA-27102错误处理
2833 0
Oracle运维笔记之ORA-27102错误处理
|
运维 Oracle 安全
Oracle运维笔记之DG主备切换后的细节修改
Oracle运维笔记之DG主备切换后的细节修改
Oracle运维笔记之DG主备切换后的细节修改
|
运维 监控 Oracle
3月19日直播【从12c到20c,Oracle多租户之10046跟踪PDB关库案例原理解析】
本次分享将针对DevOps代码质量审核、监控、开发环境测试、生产环境测试这四个方面存在的问题进行剖析并给出解决之道,希望能助您全面转型DevOps。
690 0