当前位置: 首页 > ORA > 正文

我们的文章会在微信公众号IT民工的龙马人生博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

在之前的文章中发过几篇关于ORA-00704、ORA-00604、ORA-01555错误的分析和处理,部分小伙伴觉得这种场景在工作遇得比较少,希望多发一点关于常规场景中ORA-01555错误的分析和处理,今天我们就开一个简单的系列,来简单的说明一下ORA-01555的说明、常见的场景和解决方案,本文章是一个系列文章,计划用三章来写。下面进入正题。

1.1 ORA-01555错误的本质与原理

1.1.1 错误定义

ORA-01555(Snapshot too old)是Oracle数据库中最常见的错误之一,报错信息通常为:

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

该错误的本质是:查询过程中需要的数据快照(旧版本)已经被覆盖或回收,无法保证一致性读。这与Oracle的多版本并发控制(MVCC)机制密切相关。

1.1.2 一致性读与UNDO/回滚段

Oracle通过UNDO(或早期的回滚段)来实现一致性读(除LOB特殊字段外)。当一个查询开始时,Oracle会为其创建一个一致性快照。若查询期间有DML操作(如UPDATE/DELETE),Oracle会将被修改的数据的旧版本写入UNDO表空间。查询需要访问这些旧版本时,就会去UNDO中查找。

关键点:

  • 查询本身不写UNDO,只有DML操作才会写UNDO。
  • 查询需要的UNDO是DML操作产生的,而不是查询自己产生的。
  • 如果UNDO中的旧数据被覆盖或回收,查询就无法获得一致性快照,从而报ORA-01555。

1.1.3 触发机制与误区

触发机制

  • 查询持续时间超过UNDO_RETENTION,导致所需UNDO被覆盖。
  • UNDO表空间空间不足,Oracle“偷用”未过期的UNDO块(空间压力下的“steal”机制)。
  • LOB字段的PCTVERSION/RETENTION设置不合理,导致LOB历史记录被覆盖。
  • 并发DML与查询冲突,UNDO空间压力大。
  • 罕见情况下,Oracle内部BUG也可能导致ORA-01555。
  • 特殊情况下无法在UNDO表空间中查询到UNDO段记录或者UNDO不可访问等。

常见误区

  • 误区1:为查询session指定大回滚段能避免ORA-01555。实际上,查询本身不写UNDO,指定大回滚段无效。
  • 误区2:增大rollback segment的maxextents参数能解决问题。实际上,回滚段扩展只在有未提交事务时才会发生,ORA-01555的本质是已提交事务的UNDO被覆盖。
  • 误区3:只有大表才会出现ORA-01555。实际上,任何表、任何查询,只要UNDO空间不足或查询时间过长,都可能遇到。

1.1.4 ORA-01555的详细触发流程(官方案例还原)

以官方文档(Mosid:467872.1)中的时序为例:

  1. Session #1开始查询表A。
  2. Session #2更新表A的某行X。
  3. Session #1查询到X,发现X被更新过,需要去UNDO中找旧版本。
  4. Session #2继续更新表A的Y并提交,释放了事务槽。
  5. Session #2又更新表B的Z并提交,因UNDO空间压力,Y的UNDO被覆盖。
  6. Session #1查询到Y时,发现需要的UNDO已被覆盖,报ORA-01555。

结论:
只要查询期间需要的UNDO被覆盖,无论是因为空间压力还是查询时间过长,都会触发ORA-01555。


1.2 ORA-01555的常见触发场景与案例

1.2.1 长事务/长查询

场景描述:
长时间运行的查询(如全表扫描、复杂报表、数据同步等)极易触发ORA-01555。查询开始时创建的快照需要一直保留到查询结束,期间有大量DML操作,UNDO空间中的旧数据很快被覆盖。

案例1:报表查询导致ORA-01555
某公司有一张大表SALES,每晚跑全表扫描报表,需2小时。白天有大量销售数据写入。报表查询期间,UNDO空间被持续消耗,导致ORA-01555。

案例2:游标慢fetch导致ORA-01555
某应用采用open cursor后慢慢fetch数据,fetch过程中有大量DML操作,导致需要的UNDO被覆盖,fetch到一半报ORA-01555。

1.2.2 大量DML操作导致UNDO空间被覆盖

场景描述:
即使查询本身不长,若期间有大批量DML操作(如批量更新/删除),也会导致UNDO空间迅速被消耗,覆盖旧版本数据。

案例3:批量更新导致ORA-01555
某电商平台凌晨批量更新订单状态,涉及百万数据。定时任务查询订单表时,因UNDO空间被批量DML消耗,查询需要的旧数据被覆盖,报ORA-01555。

案例4:循环提交导致ORA-01555
某应用在循环中每处理一条数据就commit,导致UNDO空间被频繁回收,其他查询需要的UNDO很快被覆盖,频繁报ORA-01555。

1.2.3 UNDO表空间配置不合理

场景描述:
UNDO表空间过小,或参数设置不合理,导致UNDO无法保留足够历史数据。

案例5:UNDO表空间过小
某企业数据库迁移后,UNDO表空间未扩容,业务量大增,DML频繁,UNDO空间很快用完。复杂查询频繁遇到ORA-01555。扩容UNDO表空间后问题解决。

1.2.4 并发查询与DML操作冲突

场景描述:
高并发环境下,多个查询和DML操作同时进行,UNDO空间竞争激烈,易引发ORA-01555。

案例6:并发操作导致ORA-01555
某金融系统月末结算时,多个批量任务并发执行,包括大批量插入、更新和查询。UNDO空间有限,部分查询任务需要的旧数据被覆盖,报ORA-01555。

1.2.5 LOB字段相关的ORA-01555

场景描述:
LOB字段的快照管理与普通数据不同,PCTVERSION/RETENTION设置不合理时,频繁更新LOB字段会导致快照丢失,报ORA-01555。

案例7:LOB字段快照丢失
某系统频繁更新含有LOB字段的大表,PCTVERSION设置过小,导致查询时无法获取旧版本LOB数据,报ORA-01555。

1.2.6 罕见的BUG或特殊场景

场景描述:
如MosID:467872.1所述,某些Oracle版本下,BUG可能导致即使查询时间为0秒也报ORA-01555。

案例8:BUG导致ORA-01555
某客户数据库在查询duration为0秒时也报ORA-01555,经查为Oracle内部BUG,需打补丁或升级版本。


1.3 ORA-01555的影响与诊断

1.3.1 对业务的影响

  • 查询失败,影响报表、统计、数据同步等业务。
  • 频繁报错影响系统稳定性和用户体验。
  • 可能导致数据一致性风险,影响业务决策。

1.3.2 诊断ORA-01555

详细诊断步骤:

  1. 收集报错信息

    • 用户端/客户端的ORA-01555报错信息。
    • 数据库alert log中的ORA-01555详细信息(包括SQL、UNDO段名、查询持续时间等)。
  2. 分析UNDO使用情况

    • 查询V$UNDOSTAT、DBA_UNDO_EXTENTS,分析UNDO空间使用、回收、被“偷用”情况。
    • 重点关注UNXPSTEALCNT(被偷用的未过期UNDO块数)、EXPSTEALCNT(被重用的已过期UNDO块数)、SSOLDERRCNT(ORA-01555错误数)。
  3. 分析SQL执行计划和事务持续时间

    • 检查SQL是否存在全表扫描、长时间未结束的事务。
    • 检查应用是否存在慢fetch、循环commit等问题。
  4. 检查LOB字段的PCTVERSION/RETENTION设置

    • 查询DBA_LOBS,确认LOB字段的快照管理参数是否合理。
  5. 排查BUG

    • 若排查无果,结合Oracle MOS文档,确认是否为已知BUG。

——————作者介绍———————–
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)


ORA-01555系列:一、ORA-01555错误的本质与原理:等您坐沙发呢!

发表评论

gravatar

? razz sad evil ! smile oops grin eek shock ??? cool lol mad twisted roll wink idea arrow neutral cry mrgreen

快捷键:Ctrl+Enter