国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

Replace函數(shù)操作CLOB導(dǎo)致臨時(shí)表空間泄露

2024-07-21 02:43:30
字體:
供稿:網(wǎng)友
工作中發(fā)現(xiàn)生產(chǎn)系統(tǒng)拋出ORA-01652錯(cuò)誤,經(jīng)過查找跑錯(cuò)的程序,發(fā)現(xiàn)是這段代碼(只是演示代碼,并不是原代碼)拋出的錯(cuò)誤:

package_body ppp

aaa clob;

...

PRocedure change_content()

begin

...

aaa := replace(aaa, 'b', ';;');

...

end;

procedure call_f()

begin

aaa := empty_clob();

aaa := 'aaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaa’

for i in 1..10000 loop

change_content();

end loop;

end;

從邏輯上看,這段代碼可以使用下面的代碼進(jìn)行模擬,

declare

aaa clob;

begin

aaa := empty_clob();

aaa := 'aaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaa’

for i in 1..10000 loop

aaa := replace(aaa, 'b', ';;');

end loop;

end;

許多人都知道,在PLSQL中的LOB類型變量是占用臨時(shí)表空間的。但是,從以上代碼看,CLOB變量aaa的初始值并沒有占用太大空間。我們?cè)跍y試環(huán)境上運(yùn)行該語句,用以下語句觀察其臨時(shí)表空間占用情況。

SELECT b.tablespace,

ROUND(((b.blocks*p.value)/1024/1024),2)||'M' "SIZE",

b.CONTENTS,

s.sql_text,

a.sid||','||a.serial# SID_SERIAL,

a.username,

a.program,

sysdate as log_date

FROM sys.v_$session a,

sys.v_$sort_usage b,

sys.v_$parameter p,

v$sqlarea s

WHERE p.name = 'db_block_size'

AND a.saddr = b.session_addr

AND a.sql_address = s.address and a.sql_hash_value = s.hash_value

ORDER BY b.tablespace, b.blocks;

TABLESPACE SIZE CONTENTS SQL_TEXT SID_SERIAL USERNAME PROGRAM LOG_DATE

---------------------------------------------------------------------------------

TEMP 37M TEMPORARY declare aaa clob; begin aaa := empty_clob(); aaa := 'aaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaa';

for i in 1..1000000000 loop aaa := replace(aaa, 'a', ';;'); end loop; end; 137,28675 DEMO plsqldev.exe 8/15/2007 11:42:11 AM

發(fā)現(xiàn)臨時(shí)表空間在不停增長。問題就在于aaa := replace(aaa, 'b', ';;').Replace()函數(shù)會(huì)先將傳入的CLOB參數(shù)變量在temp空間上保存一份,然后再轉(zhuǎn)換為varchar2類型進(jìn)行操作。這樣,每次進(jìn)行了replace操作后,就多占據(jù)了一份temp空間。

大家可以通過包dbms_lob中提供的copy、instr和write函數(shù)來自己編寫一個(gè)clob的字符替換函數(shù),來避免temp空間的泄露。以下存儲(chǔ)過程實(shí)現(xiàn)了CLOB中的字符串替換。

create or replace procedure lob_replace( p_lob in out clob,

p_what in varchar2,

p_with in varchar2 )

as

n number;

len number;

begin

n := dbms_lob.instr( p_lob, p_what );

while ( nvl(n,0) > 0 ) loop

len := dbms_lob.getlength(p_lob);

if (n+length(p_with)-1 > len)

then

dbms_lob.writeappend( p_lob, n+length(p_with)-1 - len, p_with );

end if;

if (len-n-length(p_what)+1 > 0)

then

dbms_lob.copy( p_lob,

p_lob,

len-n-length(p_what)+1,

n+length(p_with),

n+length(p_what) );

end if;

dbms_lob.write( p_lob, length(p_with), n, p_with );

if ( length(p_what) > length(p_with) )

then

dbms_lob.trim( p_lob,

dbms_lob.getlength(p_lob)-(length(p_what)-length(p_with)) );

end if;

n := dbms_lob.instr( p_lob, p_what );

end loop;

end;

結(jié)論:

使用上面的過程代替replace函數(shù),再次運(yùn)行程序,用以上語句進(jìn)行觀察,不再存在臨時(shí)空間泄露的情況。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 越西县| 巢湖市| 密山市| 工布江达县| 吴忠市| 赫章县| 藁城市| 彭山县| 平塘县| 靖州| 紫云| 望奎县| 汶上县| 涡阳县| 鹤壁市| 墨江| 周至县| 三台县| 亳州市| 诸暨市| 富民县| 黑山县| 营口市| 石阡县| 昌平区| 高阳县| 靖远县| 陕西省| 宜君县| 哈巴河县| 馆陶县| 横山县| 新化县| 大连市| 蒲江县| 噶尔县| 长沙县| 从化市| 安龙县| 原平市| 乌审旗|