--------1.引子------------------------------------------------------------------
大家都知道,针对保存在LOB段中的LOB(非IN ROW LOB),Oracle用RETENTION这个参数来控制其UNDO数据的保存.
并且,根据LOB是SECUREFILE或是BASICFILE,RETENTION的设定方式及意义是有区别的.
在此基于SECUREFILE和BASICFILE,分享下我所知道的关于RETENTION的一些知识点.
※针对BASICFILE,也可以用PCTVERSION来控制其UNDO数据的保存,此参数不在本篇讨论.
--------2.BASICFILE及SECUREFILE的 LOB RETENTION的查看及修改----------------------------------------------
2-1.如何查看是否为BASICFILE或SECUREFILE
・查看表的DDL文.
・查看dba_lobs的SECUREFILE字段,YES为SECUREFILE,NO为BASICFILE.
・查看dba_segments的SEGMENT_SUBTYPE字段,SECUREFILE为SECUREFILE,ASSM或MSSM为BASICFILE.
*ASSM或MSSM继承于表空间的设定
2-2.BASICFILE的RETENTION
2-2-1.查看
查看dba_lobs的RETENTION字段.
该值可能为NULL或包含0在内的数字.
默认值和UNDO_RETENTION相同,900(秒).
有两种情况下此值为NULL: PCTVERSION不为NULL 或LOB为SECUREFILE.
2-2-2.更改
alter system set undo_retention= 1800;--首先修改undo_retention
alter table 表名 modify lob(LOB列) (retention);--将修改后的undo_retention同步到BASICFILE的retention
alter system set undo_retention= 900;--修改完后别忘了把undo_retention再变回去
*基于上述命令可以想见针对不同表的不同LOB字段分别设定不同的RETENTION
直接执行下面这句RETENTION会被设定为NULL
altertable lobretention modify lob(lobLoc) (pctversion 5);
--5代表UNDO数据占整个LOB段的总大小的比例
--LOB段的总大小为dba_segments的MAX_SIZE字段
--MAX_SIZE为block数
2-2-3.小贴士
如果BASICFILE是手动段管理(MSSM),如果LOB段中没有可利用空间的话,即使UNDO数据的保存时间没有超过设定的RETENTION,
也会被覆盖掉.反之自动段管理(ASSM)不会发生上述情况.
即使RETENTION被设定为0,如果LOB段中有可利用空间的话,UNDO数据也会被保存而不是提交之后马上就释放掉.
2-3.SECUREFILE的RETENTION
2-3-1.查看
查看dba_segments的RETENTION字段(好端端的搬什么家),根据需要一并查看MAX_SIZE或MINRETENTION.
RETENTION的可能值如下:
DEFAULT:创建LOB时未明确指定RETENTION情况下的默认值,实际动作同AUTO AUTO :系统根据tuened_retention及LOB段的查询语句最长执行时间(来自针对该LOB段的统计情报)自动调整 MAX :当LOB段的实际大小达到dba_segments的MAX_SIZE(block数)所指定的大小时,UNDO数据开始被覆盖 MIN :根据所指定的秒数(MINRETENTION)保存UNDO数据 NONE :基本不保存UNDO数据,UNDO数据会在事务提交后马上释放
2-3-2.更改
alter table 表名 modify lob (LOB字段名) (retentionAUTO);
alter table 表名 modify lob (LOB字段名) (retention MAXstorage(maxsize 70M));
alter table 表名 modify lob (LOB字段名) (retention MIN2000);
alter table 表名 modify lob (LOB字段名) (retentionNONE);
2-3-3.小贴士
一旦将DEFAULT改为别的值之后就不能再改回DEFAULT.这种情况下改为AUTO就行了,动作是一样的
下面这句不带maxsize的设定语句能够正常执行,但会设定为AUTO而不是MAX
alter table 表名 modify lob (LOB字段名) (retentionMAX)
-------- 3. LOB RETENTION相关实用TESTCASE-----------------------------------------------------
3.1 创建BASICFILE LOB
CREATE TABLE BLOB_TEST ( ID NUMBER,B_LOB BLOB);
CREATE TABLE CLOB_TEST ( ID NUMBER,C_LOB CLOB);
3.2 创建SECUREFILE LOB
create table SECUREFILE_TEST (
c0 clob,
c1 clob,
c2 clob,
c3 clob,
c4 clob,
c5 clob)
lob (c0) store as securefile c0_lobseg
lob (c1) store as securefile c1_lobseg (retention)
lob (c2) store as securefile c2_lobseg (retention none)
lob (c3) store as securefile c3_lobseg (retention min 250)
lob (c4) store as securefile c6_lobseg (retention max storage(maxsize 50M))
lob (c5) store as securefile c7_lobseg (retention auto);
3.3 插入长度4000以内的CLOB
insert into CLOB_TEST values('101',LPAD('a', 4000, 'a'));
*有兴趣的同学可以查查12C中新追加的参数MAX_STRING_SIZE
3.4 插入大长度的CLOB
DECLARE
bigtext clob default empty_clob();
BEGIN
bigtext:= LPAD('a', 32767, 'a');
dbms_lob.append(bigtext, LPAD('a', 32767, 'a'));--这句多写几个长度就上去了
insertinto CLOB_TEST values('100',bigtext);
commit;
END;
/
3.5 shi插入BLOB
创建一个Directory
create or replace directory TEST_BLOB as 'D:TEST_BLOB';
OS中创建一个5M的测试文件(Windows为例)
fsutil file createnew D:TEST_BLOB5M.jpg 5242880
插入空LOB
insert into BLOB_TEST values('102',empty_blob());
commit;
把5M的文件更新到插入的空LOB中
declare
dest_lob blob;
src_lob bfile:=bfilename('TEST_BLOB','5M.jpg');
amount integer:=dbms_lob.getlength(src_lob);
begin
select B_LOB into dest_lob from MM0 where ID='102' for update;
dbms_lob.fileopen(src_lob);
dbms_lob.loadfromfile(dest_lob,src_lob,amount);
dbms_lob.fileclose(Src_lob);
commit;
end;
/
--------4.相关MOS文档-----------------------------------------------------
・Lob retention not changing when undo_retentionis changed (Doc ID 563470.1)
*看点:BASICFILE的RETENTION更改方法
・How to change retention of securefile Lobsegment (Doc ID 2175438.1)
*看点:SECUREFILE的RETENTION更改方法
・SECUREFILE Lob - Retention Not getting Updated(Doc ID 2174504.1)
*看点:还是SECUREFILE的RETENTION更改方法