oracle1555错误,求救:奇怪的ora-1555:snapshot too old 错误

本文详细介绍了Oracle数据库中LOB(大型对象)的读一致性机制,特别是当ORA-01555错误出现在读取LOB字段时的情况。文章解释了LOB的存储方式,包括inline和outline的区别,以及LOBINDEX如何维护数据的一致性。当PCTVERSION设置用于控制旧版本数据的保留时,如果空间不足,可能会导致ORA-01555错误。解决方法包括增加查询速度或增大PCTVERSION。当发生ORA-01555错误时,伴随的错误代码22924通常可以表明问题与LOB有关。

对于ORA-01555这个经典错误想来大家都很熟悉了,一讲到这个可以滔滔不绝

5f60efcaccfa40b26873a6a9cb266119.gif

不过当01555是发生在读取LOB字段上估计还是有人不太清楚。

想要了解这个问题,首先要说明一下oracle是如何处理LOB的读一致性的。

首先我们来建立一个含有LOB字段的表TEST

1 create table test(

2 id number,

3 pic blob)

4 lob(pic) store as pic_lob(

5 disable storage in row

6 chunk 8k

7 pctversion 10

8 nocache nologging

9 index ind_pic_lob

10* )

SQL> /

Table created.

SQL> l

1* select object_name,object_type from user_objects

SQL> /

OBJECT_NAME OBJECT_TYPE

—————————— ——————

PIC_LOB LOB

TEST TABLE

SQL> select segment_name,segment_type from user_segments;

SEGMENT_NAME SEGMENT_TYPE

—————————— ——————

TEST TABLE

IND_PIC_LOB LOBINDEX

PIC_LOB LOBSEGMENT

oracle创建了两个objects TEST这个是我们很熟悉的表了,PCT_LOB就是LOB了

创建了三个segment,一个是表,一个是LOBSEGMENT,另外一个是LOBINDEX

这个看上去好像莫名其妙的LOBINDEX就是主要为我们的LOB read consistency服务的

注意我们在创建表的时候指明了disable storage in row,所以lob存储将采取out-line的方式存储到LOBSEGMENT中。

如果是enable storage in row的话,那么长度小于3960bytes的采用in-line的方式存储,那么这时undo, redo的产生和普通的数据一样。

修改数据的时候old version存储在回滚段中,这样query可以利用undo信息重构block生成其所需的前镜像。

当采用out-line的方式存储的时候,这时读一致性可以说完全是由LOBINDEX+LOGSEGMENT来保证的。

LOBINDEX类似于B-tree的结构,存储各个LOB entry的LOB ID,LOB ID指向LOBSEGMENT中的实际存储区域。

如果要delete一条数据,删除的操作就是更新一下LOBINDEX, 并不会去将LOBSEGMENT中的内容写入回滚段中,这时候有少量的undo信息产生,但是是因为修改LOGINDEX产生的。

如果是update LOB,并不是去update原来的LOB entry,而是插入一条新的LOB entry,并且对LOB自身不产生undo信息,原来旧的数据仍然存放于LOBSEGMENT中(LOBSEGMENT中会存储相关的SCN信息)

这样query需要读取old version的数据就不是从回滚段中读取old value来重构,而是从LOBSEGMENT中读取原先的LOB entry。

如果delete,update操作很多,oracle会不会一直保存这些old version的数据呢?答案是不会。

这时就靠我们上面在创建LOB时的参数PCTVERSION来控制了。PCTVERSION=10的含义就是在HWM下留有10%的空间用于存放Old version的数据.

如果存放old version的空间多于PCTVERSION,那么就可以被重用。这时如果有query需要重构旧的数据,就会产生ORA-01555错误。

想要避免01555的话一个就是尽量缩短query的时间,另外就是增大PCTVERSION,当然这会消耗更多的空间存放旧数据。

那么最后一个问题是如果辨别ORA-01555是不是发生在LOB上的

一般来说,普通的01555错误会指明发生01555的rollback segment,而LOB的则没有,而是伴随着ORA-22924出现

xfan-tiger1$> oerr ora 22924

22924, 00000, “snapshot too old”

// *Cause: The version of the LOB value needed for the consistent read was

// already overwritten by another writer.

// *Action: Use a larger version pool.

xfan-tiger1$> oerr ora 01555

01555, 00000, “snapshot too old: rollback segment number %s with name \”%s\” too small”

// *Cause: rollback records needed by a reader for consistent read are

// overwritten by other writers

// *Action: If in Automatic Undo Management mode, increase undo_retention

// setting. Otherwise, use larger rollback segments

这个人的回复好像可以,看来我理解错了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值