问题描述

20231127上午客户反馈绩效系统20231125、20231126出现2次YAS-02020 snapshot too old的问题,测试也有类似问题。

该过程是客户新增的存储过程,目的是通过PRO_RUN_JOB作为主控,调度其他存储过程,后续不用其他调度引擎。

原因分析

错误信息收集分析

分析存储过程报错日志,核查UNDO_RETENTION、undo表空间

看了相应的优化建议,可以增大参数UNDO_RETENTION的值,或者使用更大的undo表空间。

客户环境目前UNDO_RETENTION配置了600,该参数单位是秒。临时修改客户测试环境的配置为3000,试图规避问题。

正常理解,MVCC用于高并发的情形,会出现该错误,而该存储过程执行是串行的,不符合预期!需要继续分析。

UNDO、MVCC机制分析

了解背后机制,snapshot too old是由于db需要做多版本控制(mvcc),在数据commit之后,仍然会保留undo一段时间,在超过这段时间之后undo的空间会被复用,如果需要还原的数据超过了这个时间,则还原不了,触发该错误。

崖山db快照隔离级别的核心就是MVCC(Multi-Version Concurrency Control),多版本并发控制

快照本质上就是一个时间点。记录版本的时间点为事务提交的时间点。

可见性可分为2类情况:

1、事务内的语句可见性

2、事务间的可见性

由于老版本保留时间的限制,我们可能无法读取到某些很老的版本,这时就会有snapshot too old错误。

事务功能梳理 - YashanDB

可以确认:

  • 不同事务间,特别是长查询,容易出现该问题;

  • 另一个是专门的快照读,如Oracle的快照读select count(*) from tableA as of timestamp to_timestamp('2013-10-16 08:46:57','yyyy-mm-dd hh24:mi:ss');

疑点一

分析测试环境出现过类似的问题,看到报错的时间点:

2023/11/23 13:21:52执行的是PRO_DAILY_DPSIT

2023/11/23 12:04:00执行的是PRO_SYS_USER_POST_REL

有个共同点:

PRO_SYS_USER_POST_REL用的是merge,同时读和写同个表

PRO_DAILY_DPSIT用的是insert into select,insert 和select的表有相同的

开始怀疑这里有并发机制,读写自同个表,但是作为同个事务内的,undo不应该被释放掉,不符合预期!

确认问题

剩下的就是长查询的可能。只有在查询的时候才会报这个错误,update的时候是不会报这个错误的。

继续分析游标loop的结果,如果在游标读取的时候报错,则remark也是:更新跑数任务明细表:单个任务成功结束的相关信息

fetch在一开始就拿到scn(SCN即系统改变号(System Change Number)),每次fetch都用的open时的scn,由于loop过程中还是update RUN_JOB_DETA表更新了db存储的某一个block,commit之后undo的数据会保留undo_retention的时间,当超过这个时间undo的空间会别其他任务复用。

而一个block不止一条数据,在后续loop的过程,如果继续读取到这个block的数据,需要对这个block还原到scn对应的状态再读取,由于undo已经被复用,就会报snapshot too old的错误。

undo机制、MVCC机制,在Oracle、DB2中都是有的,该问题也会存在。崖山的数据块不会存2个表的数据,可以使用下面方法规避:

PRO_RUN_JOB这个存储过程使用游标读取RUN_JOB_DETA表做为配置表,loop过程中需要更新的结果数据放到历史表(主要更新任务状态,开始、结束时间,耗时),配置表和历史结果分开存储,彻底解决问题。

经验教训

  • Undo机制中,undo_retention是一个不容易理解的参数项。设置之后,Oracle会根据自动undo管理的原则进行调节,进行空间拓展,来适应实现用户的期间要求。而崖山db需要根据实际的业务频繁度和数量量、以及undo表空间设置情况进行综合评估。

  • 存储过程存在游标遍历,需要注意更新目标表不是fetch的表,否则存在类似问题。

【YashanDB知识库】存储过程报错snapshot too old的更多相关文章

  1. TFDStoredProc执行sql server的部分存储过程报错,有的是好的。

    TFDStoredProc执行sql server的部分存储过程报错,有的是好的. Invalid character value for cast specification 暂时无解.用fdque ...

  2. Mybatis调用存储过程报错

    Mybatis调用存储过程 贴码 123456 Error querying database. Cause: java.sql.SQLException: User does not have ac ...

  3. mysql 创建存储过程报错

    在创建存储过程前把结束符定义为 delimiter // 然后再创建就不会报错

  4. C# 调用存储过程 Sql Server存储过程 存储过程报错,程序中的try

    C#程序调用Sql Server存储过程,存储过程中报错情况,返回值... 0.SQL存储过程 USE [Opos] GO /****** Object: StoredProcedure [dbo]. ...

  5. java 执行mysql 8.0.11存储过程报错The user specified as a definer ('root'@'10.%.%.%') does not exist解决办法

    执行存储过程,报错 java.sql.SQLException: The user specified as a definer ('root'@'10.%.%.%') does not exist ...

  6. 执行存储过程报错——ora-01031:权限不足

    1. 执行DDL报错 在oracle存储过程中,默认是可以直接执行DML和DQL的,但是执行CREATE这种的DDL则需要借助EXECUTE IMMEDIATE ···了,如下备份表语句 --抄表表备 ...

  7. 在mybatis中使用存储过程报错java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列: PLS-00905: 对象 USER1.HELLO_TEST 无效 ORA-06550: 第 1 行, 第 7 列:

    hello_test是我的存储过程的名字,在mapper.xml文件中是这么写的 <select id="getPageByProcedure" statementType= ...

  8. navicat创建存储过程报错

    搞了半天这个恶心的报错,最后发现竟然是存储过程的一个varchar类型的参数没给长度,如varchar(64)长度必须指定不然就会报错: mark一记

  9. Oracle执行存储过程报错——ora-01031:权限不足

    执行DDL报错 在oracle存储过程中,默认是可以直接执行DML和DQL的,但是执行CREATE这种的DDL则需要借助EXECUTE IMMEDIATE 如: create or replace p ...

  10. PHP多次调用Mysql存储过程报错解决办法

    PHP多次调用Mysql数据库的存储过程会出现问题,主要问题为存储过程中执行多次SQL语句不能一一释放导致的,网上找了一些解决办法,比如使用 multi_query 然后一个一个释放,但是发现根本不适 ...

随机推荐

  1. Java(screw)生成数据库表结构

    数据库支持 MySQL MariaDB TIDB Oracle SqlServer PostgreSQL Cache DB(2016) 文档生成支持 html word markdown 方式一:代码 ...

  2. SpringBoot集成日志框架

    springboot默认日志是打印在console中,不会保存在文件中.我们项目上线肯定要保存日志用于分析问题的. 使用xml配置日志保存 并不需要pom配置slf4j依赖,starter里面已经配置 ...

  3. Mac VMware Fusion 11.5 虚拟机带密钥

    虚拟机 链接: https://pan.baidu.com/s/19V20p5ZV-1U5lFNHrotLgw 密码: rdun CentOS 6.5 链接: https://pan.baidu.co ...

  4. CF1468N 题解

    洛谷链接&CF 链接 题目简述 共有 \(T\) 组数据,对于每组数据: 有三个桶,五种垃圾,每个桶有固定的容量. 前三种垃圾分别放入三种桶中,第四种垃圾可以放进 \(1,3\) 桶中,第五种 ...

  5. Vue 基于VSCode结合Vetur+ESlint+Prettier统一Vue代码风格

    基于VSCode结合Vetur+ESlint+Prettier统一Vue代码风格 插件安装 安装Vetur,ESlint, Prettier - Code formatter插件 安装方法(安装ESl ...

  6. 🚀RabbitMQ+redis+Redisson分布式锁+seata实现订单服务

    引言 订单服务涉及许多方面,分布式事务,分布式锁,例如订单超时未支付要取消订单,订单如何防止重复提交,如何防止超卖.这里都会使用到. 开启分布式事务可以保证跨多个服务的数据操作的一致性和完整性, 使用 ...

  7. 标准 C++ 中的 string 类的用法总结

    相信使用过 MFC 编程的朋友对 CString 这个类的印象应该非常深刻吧?的确,MFC 中的 CString 类使用起来真的非常的方便好用.但是如果离开了 MFC 框架,还有没有这样使用起来非常方 ...

  8. 巧用 QLineF 从 QTransform 提取角度

    我们在对 QGraphicsItem 进行变换时,QT 提供了很多便捷的方法.但当我们想获取当前变换的角度时却有些困难,因为 QTransform 没有提供获取角度的方法.在文章Qt 从 QTrans ...

  9. MapGIS路网数据发布

    准备 1.MapGIS 10 桌面版(我用的10.5.6.10) 2.路网的shp文件 数据导入 1.创建要素集,如果已有要素集可以不用创建: 2.导入路网要素类,选择准备好的shp文件后导入即可: ...

  10. 【Mybatis】07 万用Map & 模糊查询细节

    这应该算一个补充点 在尚硅谷的Java笔记资料有专门的一起万用Map讲解 参考自:https://www.bilibili.com/video/BV1NE411Q7Nx?p=5 万用Map 我们可以使 ...