Oracle 修改LOB字段PCTVERSION 的方法
最近已经有好几位网友找我咨询怎么处理ORA-0155和ORA-22924错误了,错误信息都一样,如下:
ORA-01555: snapshot too old: rollback segment number with name "" too small ORA-22924: snapshot too old
在告警日志中,常见的ORA-01555错误基本都会伴随着SQL语句,并且说明SQL运行多少秒报错,一般遇到这个错误,SQL运行的时间都会很长,也有一种情况,就是SQL运行时间 为0,这基本是由于SQL中指定了时间或者SCN查询,而回滚段不满足查询指定的时间,就会显示SQL运行时间为0的情况。
ORA-01555都是快照过旧,回滚段太小或者是回滚段保留时间太小导致的,但ORA-22924伴随这ORA-01555一起出现,基本都是和LOB有关。之前曾写过关于这个问题的文章,LOB回滚段快照过旧ORA-22924 snapshot too old,遇到这样的错误,基本都和表的设计不正确有关,很多人建表都习惯用默认值,对生产数据库来讲,默认值很多时候是满足不了业务需求的。本文将按照我的习惯,来创建一张包含CLOB字段的测试表,并说明一些需要注意的地方,希望对大家有所帮助。
本案例测试数据库为11.2.0.4版本,这里提一下11g专门针对LOB字段的新特性securefile,这是在11g推出的新的LOB存储模式,之前的版本都是以basicfile方式存储LOB字段,securefile于basicfile相比,对LOB的读取和写入操作的效率均有明显提高,但却需要占用更多的磁盘空间,但也多的有限,基本可以忽略不计。在11g版本,默认的LOB存储模式还是basicfile,如果使用securefile,需要在建表的时候指定或者数据库securefile相关的参数才可以,个人建议LOB都以securefile存储。
建议将LOB存放在独立的表空间中,下面创建本案例存放LOB的表空间。
sys@IVLDB> CREATE TABLESPACE LOB_TBS DATAFILE '/u01/app/oracle/oradata/ivldb/lob_tbs01.dbf' SIZE 10M AUTOEXTEND ON; Tablespace created. sys@IVLDB> CONN dbdream/dbdream Connected.
下面创建含有LOB字段的表,表结构还是按照上文引用文章的表,只是第二个CLOB改成了BLOG。
dbdream@IVLDB> CREATE TABLE T_RESTREE 2 ( C_RESID VARCHAR2(255) NOT NULL ENABLE, 3 C_RESNAME VARCHAR2(255), 4 C_RESTYPE VARCHAR2(255), 5 C_PERM CLOB, 6 C_RESDESC VARCHAR2(255), 7 C_STATUS VARCHAR2(255), 8 C_LASTMODIFIED DATE, 9 C_RESALIAS VARCHAR2(255), 10 C_CREATED DATE, 11 C_ORDER NUMBER(*,0), 12 C_EXTENDED BLOB, 13 C_PID VARCHAR2(255), 14 PRIMARY KEY (C_RESID) 15 ) SEGMENT CREATION IMMEDIATE 16 TABLESPACE USERS 17 LOB (C_PERM) STORE AS SECUREFILE ( 18 TABLESPACE LOB_TBS ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 20) 19 LOB (C_EXTENDED) STORE AS SECUREFILE ( 20 TABLESPACE LOB_TBS DISABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10) 21 ; Table created.
下面解释下建表语句中的几处需要注意的地方。
SEGMENT CREATION IMMEDIATE,这也是11g的一个新特性,叫延迟段创建,默认值是SEGMENT CREATION DEFERRED,也就是在创建一个新表的时候,不为表分配段,也就是不分配磁盘空间,这样的表exp导不出来,在习惯使用exp的人来讲,很坑爹,还有一个值就是SEGMENT CREATION IMMEDIATE,也就是在创建新表的时候,为表分配段。
STORE AS SECUREFILE,此处指定LOB的存储模式是securefile,默认是basicfile模式。
ENABLE STORAGE IN ROW,此处表示将LOB字段存放到行内,如果LOB字段小于4000字节,才会将LOB字段和其他字段放到一次存放,如果LOB字段超过4000字节,LOB字段将单独存放,因此大部分都是CLOB使用,BLOB通常都较大,因此上面的案例BLOB使用的是DISABLE STORAGE IN ROW,禁用了BLOB字段和其他字段一起存放。
PCTVERSION,这是本文的重点,导致ORA-0155和ORA-22924错误错误的元凶就是它了,上文的建表语句可以看到,CLOB设置的PCTVERSION值是20,BLOB设置的PCTVERSION值是10,PCTVERSION是说,存放LOB的数据块的百分之多少预留给LOB做回滚段,因为BLOB基本不会在数据库里直接被修改,因此预留10%的回滚段基本是够用的,10%也是默认值,当然如果修改的多,可以适当调整,CLOB字段在数据库中就可能有修改操作了,默认10%基本是不够用的,因此上文建的表,CLOB的PCTVERSION设置的是20%。
如果已经遇到ORA-0155和ORA-22924错误,或者预防遇到这样的错误,可以通过下面的命令修改LOB字段的PCTVERSION设置,比如将上面建的表的BLOB字段的PCTVERSION从10修改为20,如下:
dbdream@IVLDB> ALTER TABLE T_RESTREE MODIFY LOB(C_EXTENDED) (PCTVERSION 20); Table altered.