事务槽引起的 ORA-600 事件

发布时间:2020-08-19 06:59:22 作者:Ryan_Bai
来源:ITPUB博客 阅读:169

问题描述

执行 update 时出现告警:

ORA-00600: 内部错误代码, 参数: [4521], [11], [18446744073606860068], [11], [399824003], [18446744073709551615], [18446744073709551615], [], [], [], [], []

事务槽引起的 ORA-600 事件

相关概念

ITL描述

ITL(Interested Transaction List) 是 Oracle 数据块内部的一个组成部分,位于数据块头(block header),itl 由 xid,uba,flag,lck 和 scn/fsc 组成,用来记录该块所有发生的事务,一个 itl 可以看作是一条事务记录。当然,如果这个事务已经提交,那么这个 itl 的位置就可以被反复使用了,因为 itl 类似记录,所以,有的时候也叫itl槽位。如果一个事务一直没有提交,那么,这个事务将一直占用一个itl槽位,itl里面记录了事务信息,回滚段的入口,事务类型等等。如果这个事务已经提交,那么,itl 槽位中还保存的有这个事务提交时候的 SCN 号。

ITL个数其最小值为 1,由参数 initrans 控制(由于兼容性的原因,oracle 会在对象的存储块分配两个itl,所以 initrans 的最小值实际上为 2),最大值为 255,由参数 maxtrans 控制,最大值参数在 10g 以后不能被修改,itl 是 block 级的概念,一个 itl 占用块 46B 的空间,参数 initrans 意味着块中除去 block header 外一部分存储空间无法被记录使用(46B*initrans),当块中还有一定的 free space 时,oracle 可以使用 free space 构建 itl 供事务使用,如果没有了 free space,那么,这个块因为不能分配新的 itl,所以就可能发生 itl 等待。

简述一下事务的流程

  1. 开始一个事务,首先Oracle给这个事务分配XID,并找到一个回滚段,在回滚段头块将事务信息存放在事务表中,并给这个事务分配undo块,并将undo块的地址也写入事务表中(UBA地址) 。

  2. 事务准备修改一个数据块,在该数据块的头部的事务槽中写入事务信息(XID ,UBA(这个UBA指向相对应的undo块))。

  3. 开始修改数据,将数据块修改的前映像存放在 undo 块中。

问题信息获取

一般ORA-600的错误都会在后台进行记录,下面是我们找到的记录内容

事务槽引起的 ORA-600 事件

根据记录内容,我们可以获取到相应的trace文件,仔细查看可知如下信息

  1. 异常语句(红色遮住的部分为语句,由于涉及的客户语句,且与本博客无关,所以此处不显示)
    事务槽引起的 ORA-600 事件

  2. 涉及到的函数
    事务槽引起的 ORA-600 事件

  3. ERROR的原因
    事务槽引起的 ORA-600 事件

  4. ITL 槽被占用了 24 个
    事务槽引起的 ORA-600 事件

  5. 产生了大量的行锁
    事务槽引起的 ORA-600 事件

原因分析

根据 mos,比对现象发现

  1. 版本复合,错误一致
    事务槽引起的 ORA-600 事件

  2. 函数调用一致
    事务槽引起的 ORA-600 事件

  3. 原因则是ITL事务槽满造成的该事件

解决方案

通过重新创建表或索引并修改 INITRANS 或 PCTFREE 参数来增加表或索引的ITL能力,以便能够处理更多并发事务。

  1. 增加INITRANS

    1. 根据表中事务的数量,我们需要改变初始值。这里改为 50:

      alter table <表名> INITRANS 50;
    2. 然后使用move重新组织表(alter table move;)

    3. 然后重新构建这个表的所有索引,如下所示

      alter index <索引名> rebuild INITRANS 50;
  2. 增加 PCTFREE
    如果增加 INITRANS 不能解决这个问题,那么尝试增加 PCTFREE。增加 PCTFREE 会保留更多的空间,因此将相同数量的行分散到更多的块上。总的来说,这意味着有更多的 ITL 插槽可用。

    1. 将行扩展到更多的块中也有助于减少这个等待事件。

      alter table <表名> PCTFREE 20
    2. 然后使用move重新组织表(alter table move;)

    3. 重建索引

      alter index <索引名> rebuild PCTFREE 20
  3. 增加 INITRANS 和 PCTFREE 的组合

    1. 将 INITRANS 设置为 50,pct_free 设置为 20

      alter table <表名> PCTFREE 20 INITRANS 50
    2. 使用 move 重新组织表(alter table move;)

    3. 然后重新构建表的所有索引,如下所示

      alter index <index_name> rebuild PCTFREE 20 INITRANS 50;

参考

推荐阅读:
  1. oracle 12.1的那些坑
  2. Oracle 12.2 BUG :分区维护导致的 ORA-600 KKPOFPCD3

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

ora- 600

上一篇:shell脚本实现多台服务器自动巡检--可参考学习

下一篇:Linux 下nohup 和 &有什么联系呢?

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》