事务槽引起的ORA-600事件

问题描述

执行 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  rebuild PCTFREE 20 INITRANS 50;

参考

  • ORA-00600: Internal Error Code, Arguments: [4521] (Doc ID 2648741.1)

  • Troubleshooting waits for 'enq: TX - allocate ITL entry' (Doc ID 1472175.1)


文章标题:事务槽引起的ORA-600事件
文章分享:http://scyanting.com/article/gdhepp.html