oracle clob压缩,Oracle 10.2.0.3上压缩CLOB时的Corruption及其对应

服务器上有一Application,保存有30G的CLOB数据。

虽然每周定时将一些CLOB退避到OS,还是发生了Tablespace不够用的现象(使用率约100%)。

经过反复调查发现,CLOB使用的LOBSegment在删除CLOB信息后,并不自动向Tablespace返回空白空间,这就造成其他数据需要空间时出现错误。

所以需要通过SQL整理,使其返回空白的空间。

从10.2开始,Oracle提供了压缩LOBSegment的功能(Shrink Space)。可以执行以下语句。

ALTER TABLE mi.FILE_ITEM_DATA MODIFY LOB (ITEM_DATA)(SHRINK SPACE);

中途出现了ArchiveLog领域不够用等时间(这个整理发生Redolog的)后,经过6个多小时的处理,终于结束了。

可是,很不幸,在进行例行的Expdp(export)时,出现错误。

ORA-02354: error in exporting/importing data

ORA-01555: snapshot too old: rollback segment number with name " " too small

ORA-22924: snapshot too old

经过support.oracle的查证,发现这是10.2.0.3.0的一个Bug。(Bug. 5636728,  参考Oracle文件,编号为833635.1)

SHRINK SPACE会引起LOB数据破损(Corruption)。

如何解决呢? 如果你保存有破损前的备份,根据833635.1文件,可采取以下对策。

(幸好,我每天都做EXPORT。“Export不是备份的好办法,你应该用RMAN。”好的,那是另外一个问题。)

1. 首先查出破损的数据所在的RowID。

create table corrupted_lob_data (corrupted_rowidrowid);

set concat off

declare

error_1555exception;

pragmaexception_init(error_1555,-1555);

num number;

begin

forcursor_lob in (select rowid r, ITEM_DATA from mi.FILE_ITEM_DATA) loop

begin

num :=dbms_lob.instr (cursor_lob.ITEM_DATA, hextoraw ('889911')) ;

exception

whenerror_1555 then

insertinto corrupted_lob_data values (cursor_lob.r);

commit;

end;

end loop;

end;

/

2. 做个临时表放置破损的记录

Create table MI.FILE_ITEM_DATA_ANX as

Select * from MI.FILE_ITEM_DATA

where rowid in ( select * from corrupted_lob_data );

3. Export以备后用

bash-3.00$ expdp \"/ as sysdba\"tables=MI.FILE_ITEM_DATA_ANX dumpfile=MI-clob-anx.dmp directory=dpump_dir

4. 传送所需文件到测试机

把破损前的EXPORT文件传送到测试机。

把刚才(步骤3)生成的Export文件传送到测试机。

———————— 在另一台测试机上-----------------

5. 准备测试机上的环境

如果在测试机上没有该用户的空间,那你就首先做Tablespace,然后定义用户。

麻烦?不要紧。

你可以在生产机上通过以下SQL语句获取这些信息。

set long 5000

select dbms_metadata.get_ddl('TABLESPACE',  'MI_SPC') from dual;

这里,MI_SPC是Tablespace名称。

select dbms_metadata.get_ddl('USER',  'MI') from dual;

这里,MI是USER名称。

6. Import步骤4的两个文件。

bash-3.00$ impdp userid=\'/ as sysdba\'dumpfile=MI-1030.dmp directory=dpump_dir schemass=MI

bash-3.00$ impdp userid=\'/ as sysdba\'dumpfile=MI-clob-anx.dmp directory=dpump_dir tables=MI.FILE_ITEM_DATA_ANXtable_exists_action=REPLACE

7. 从破损前的表中恢复CLOB数据

UPDATE MI.FILE_ITEM_DATA_ANX A

SET item_data = (SELECT item_data fromMI.FILE_ITEM_DATA B WHERE B. FILE_ITEM_DATA_ID = A. FILE_ITEM_DATA_ID)

where exists (SELECT 1 from MI.FILE_ITEM_DATA B1WHERE B1. FILE_ITEM_DATA_ID = A. FILE_ITEM_DATA_ID);

可以使用以下SQL语句检查

select * from MI.FILE_ITEM_DATA_ANX where rownum=1;

8. Export以备后用

bash-3.00$ expdp \"/ as sysdba\" tables=MI.FILE_ITEM_DATA_ANXdumpfile=MI-clob-anx.dmp directory=dpump_dir

9. 把刚才(步骤8)生成的Export文件传送(ftp)到测试机。

———————————— 回到生产机-------------------

10. import

bash-3.00$ impdp userid=\'/ as sysdba\'dumpfile=MI-clob-anx.dmp directory=dpump_dir tables=MI.FILE_ITEM_DATA_ANXtable_exists_action=REPLACE

11. 恢复原来表中的CLOB数据

UPDATE MI.FILE_ITEM_DATA B

SET item_data = (SELECT item_data fromMI.FILE_ITEM_DATA_ANX A   WHEREA.FILE_ITEM_DATA_ID = B.FILE_ITEM_DATA_ID)

WHERE EXISTS (Select 1  from MI.FILE_ITEM_DATA_ANX A1 WHEREA1.FILE_ITEM_DATA_ID = B.FILE_ITEM_DATA_ID);

12. 有必要的话,检查是否恢复。

set concat off

set serveroutput on

declare

error_1555exception;

pragmaexception_init(error_1555,-1555);

num number;

begin

forcursor_lob in (select rowid r, ITEM_DATA from mi.FILE_ITEM_DATA) loop

begin

num :=dbms_lob.instr (cursor_lob.ITEM_DATA, hextoraw ('889911')) ;

exception

whenerror_1555 then

--insert into corrupted_lob_data values (cursor_lob.r);

--commit;

dbms_output.put_line(cursor_lob.r);

end;

end loop;

end;

/

如果没有ROWID输出,那就大功告成了。

后记

这个Shrink Space既然有Bug,如何解决呢?

你可以升级到10.2.0.4。

可是升级是很麻烦的事情。即使是版本号码第4位的变动(比如这里,从3到4),也要进行周密的用户程序测试。

别忘了墨菲定律:再重要的软件,也至少会有一个bug。

再说了,Oracle也这么建议。

版本升级也那么麻烦?

没有更简单的办法了?

Oracle的Helpdesk说,

可以用Move代替Shrink Space。

(休止)ALTERTABLE mi.FILE_ITEM_DATA MODIFY LOB (ITEM_DATA) (SHRINK SPACE);

(启用) alter table mi.file_item_data movelob(ITEM_DATA) store as (tablespace mi_spc);

这里,tablespace的名称不变,就是说,在相同的表领域移动也可以有压缩效果(测试完毕)。

这样还是不能一劳永逸。还有一个办法就是

给LOB专门做一个Tablespace。

这又是另一个话题。且听下回分解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值