首页 » ORACLE 9i-23ai » Know more about Temporary Tablespaces ORA-1652 and event 60025 temp space never release

Know more about Temporary Tablespaces ORA-1652 and event 60025 temp space never release

众所周知, oracle临时表空间是用于存储数据库的排序数据和全局临时表数据,tempfile不同于datafile因为不存在控制文件中,在恢复数据库后需要重建tempfile,也可以在standby环境中配置不同的temp表空间。用监控数据表空间间的脚本也许看到临时表空间使用率100%,但并且有时并非真实,DBA_FREE_SPACE 不会记录临时表空间的可用空间,使用v$sort_segments, V$TEMP_SPACE_HEADER 和v$tempseg_usage监控临时表空间的使用,如果临时表空间不足会提示ORA-1652错误。对于临时表空间组特性是没有用的,为不同的用户分配不同的temp tablespace并且以用户分配到不同的实例可以减少temp空间争用。

临时表空间是被分成不同的extent,在11g r2中每个extent为1MB,extent maps是cache在本地的SGA中,并在再重启时不会保存extent map,所以在实例重启后可以完全释放临时表空间的扩展, 临时表空间(cache extent map)是按需扩展的,用完后会标记为free但不会回收(如果不重启),可以使用v$tempseg_usege查看当前实际使用。本实例cache的extent即使为free,对于其他实例也不可以立即使用,另一个实例需要申请新的uncache的extent, free extent只重用于本实例请求。当一个实例需要更多的extent时可以从另一个实例偷窃,另一个实例会uncache extent map,可以从gv$temp_extent_pool中观察,在11g中为一次请求100 extents,当本实例窃取够了足够的extent就可以继续使用temp extent,临时段的清理或合并是有每5分钟smon进程完成的。

SQL> select * from gv$temp_extent_pool;

   INST_ID TABLESPACE_NAME      FILE_ID EXTENTS_CACHED EXTENTS_USED BLOCKS_CACHED BLOCKS_USED BYTES_CACHED BYTES_USED RELATIVE_FNO
---------- ----------------- ---------- -------------- ------------ ------------- ----------- ------------ ---------- ------------
         1 TEMP                       1          11916            8       1525248        1024   1.2495E+10    8388608            1
         1 TEMP                       3           2884            1        369152         128   3024093184    1048576            3
         1 TEMP                       4           5990            3        766720         384   6280970240    3145728            4
         1 TEMP                       5           9422            1       1206016         128   9879683072    1048576            5
         1 TEMP                       6          10659            3       1364352         384   1.1177E+10    3145728            6
         2 TEMP                       1          18347            0       2348416           0   1.9238E+10          0            1
         2 TEMP                       3          12474            2       1596672         256   1.3080E+10    2097152            3
         2 TEMP                       4           9369            0       1199232           0   9824108544          0            4
         2 TEMP                       5           5937            3        759936         384   6225395712    3145728            5

近期有一套数据库出现了ORA-1652,extent map都已cache,显示使用率为100%,但当前真实使用的并不多,重启数据库不现实,我想通过drop tempfile再填加的方式释放已扩展的temp空间,结果发现了一个有意思的事情。

1, Drop Tempfile

SQL> @df

TABLESPACE_NAME                   TotalMB     UsedMB     FreeMB % Used Ext Used
------------------------------ ---------- ---------- ---------- ------ --- ----------------------
...
SYSAUX                              24318      17012       7306    70% NO  |##############      |
SYSTEM                              20478       2674      17804    14% NO  |###                 |
TEMP                               107517     107474         43   100% YES |####################|
UNDOTBS1                            61438      35678      25760    59% NO  |############        |
UNDOTBS2                            61438      13743      47695    23% NO  |#####               |
USERS                              330226     283772      46454    86% NO  |##################  |

SQL> @ls temp

TABLESPACE_NAME                   FILE_ID FILE_NAME                                EXT         MB      MAXSZ
------------------------------ ---------- ---------------------------------------- --- ---------- ----------
TEMP                                    3 /dev/yyc_oravg02/ryyc_lv15_128           NO       15359
TEMP                                    1 /dev/yyc_oravg02/ryyc_temp               YES      30719   32767.98
TEMP                                    2 /dev/yyc_oravg03/ryyc_lv15_240
TEMP                                    4 /dev/yyc_oravg04/ryyc_lv15_281           NO    15359.99
TEMP                                    5 /dev/yyc_oravg04/ryyc_lv15_282           NO    15359.99
TEMP                                    6 /dev/yyc_oravg04/ryyc_lv15_283           NO    15359.99
TEMP                                    7 /dev/yyc_oravg04/ryyc_lv15_284           NO    15359.99

SQL> alter tablespace temp drop tempfile '/dev/yyc_oravg04/ryyc_lv15_284';
Tablespace altered.

SQL> alter tablespace temp drop tempfile '/dev/yyc_oravg04/ryyc_lv15_283';
Tablespace altered.

SQL> alter tablespace temp add tempfile '/dev/yyc_oravg04/ryyc_lv15_284';
alter tablespace temp add tempfile '/dev/yyc_oravg04/ryyc_lv15_284'
*
ERROR at line 1:
ORA-01537: cannot add file '/dev/yyc_oravg04/ryyc_lv15_284' - file already part of database

SQL> @ls temp
TABLESPACE_NAME                   FILE_ID FILE_NAME                                                                        EXT         MB      MAXSZ
------------------------------ ---------- -------------------------------------------------------------------------------- --- ---------- ----------
TEMP                                    3 /dev/yyc_oravg02/ryyc_lv15_128                                                   NO       15359
TEMP                                    1 /dev/yyc_oravg02/ryyc_temp                                                       YES      30719   32767.98
TEMP                                    2 /dev/yyc_oravg03/ryyc_lv15_240
TEMP                                    4 /dev/yyc_oravg04/ryyc_lv15_281                                                   NO    15359.99
TEMP                                    5 /dev/yyc_oravg04/ryyc_lv15_282                                                   NO    15359.99
TEMP                                    6 /dev/yyc_oravg04/ryyc_lv15_283
TEMP                                    7 /dev/yyc_oravg04/ryyc_lv15_284

SQL> @df

TABLESPACE_NAME                   TotalMB     UsedMB     FreeMB % Used Ext Used
------------------------------ ---------- ---------- ---------- ------ --- ----------------------
...
SYSAUX                              24318      17014       7304    70% NO  |##############      |
SYSTEM                              20478       2674      17804    14% NO  |###                 |
TEMP                                76797      76754         43   100% YES |####################|
UNDOTBS1                            61438      35678      25760    59% NO  |############        |
UNDOTBS2                            61438      13726      47712    23% NO  |#####               |
USERS                              330226     283772      46454    86% NO  |##################  |

NOTE:
使用alter tablespace无法drop tempfile(从数据库释放tempfile),但是可用空间被收回。 正确的方法是使用alter database方式如下:

SQL> alter database tempfile '/dev/yyc_oravg03/ryyc_lv15_240'  drop including datafiles;
Database altered.

SQL> @ls temp

TABLESPACE_NAME                   FILE_ID FILE_NAME                                                                        EXT         MB      MAXSZ
------------------------------ ---------- -------------------------------------------------------------------------------- --- ---------- ----------
TEMP                                    3 /dev/yyc_oravg02/ryyc_lv15_128                                                   NO       15359
TEMP                                    1 /dev/yyc_oravg02/ryyc_temp                                                       YES      30719   32767.98
TEMP                                    4 /dev/yyc_oravg04/ryyc_lv15_281                                                   NO    15359.99
TEMP                                    5 /dev/yyc_oravg04/ryyc_lv15_282                                                   NO    15359.99
TEMP                                    6 /dev/yyc_oravg04/ryyc_lv15_283
TEMP                                    7 /dev/yyc_oravg04/ryyc_lv15_284

Note:
drop tempfile或drop temporary tablespace前提是当前无会话使用该文件和表空间,如果删除了所有的tempfile,在使用时会提示ora-25153错误,如果有会话使用该tempfile将报ORA-25152错误。

SQL> alter database tempfile '/dev/yyc_oravg04/ryyc_lv15_284'  drop including datafiles;
alter database tempfile '/dev/yyc_oravg04/ryyc_lv15_284'  drop including datafiles
*
ERROR at line 1:
ORA-25152: TEMPFILE cannot be dropped at this time

SQL> select u.inst_id,s.sid,s.status,tablespace,u.sql_id,segfile#,segfile#-p.value rfile 
from gv$tempseg_usage u,v$parameter p,gv$session s 
where u.session_addr = s.saddr AND u.inst_id = s.inst_id and p.NAME='db_files';

   INST_ID        SID STATUS   TABLESPACE                      SQL_ID            SEGFILE#      RFILE
---------- ---------- -------- ------------------------------- --------------- ---------- ----------
         1      17813 INACTIVE TEMP                            cbpmfx12jzj4r         2025          1
         1      17530 INACTIVE TEMP                            64tcqftuuwaan         2028          4
         1      17285 INACTIVE TEMP                            cbpmfx12jzj4r         2025          1
...
         2       4814 INACTIVE TEMP                            cbpmfx12jzj4r         2025          1
         2       4806 INACTIVE TEMP                            6h214g82rxb7x         2027          3
         1       4319 INACTIVE TEMP                            64tcqftuuwaan         2030          6
         1       1776 INACTIVE TEMP                            a6kb0pf8x0hqc         2029          5
         2         51 INACTIVE TEMP                            cbpmfx12jzj4r         2025          1
         1        285 INACTIVE TEMP                            6h214g82rxb7x         2031          7
         1          4 INACTIVE TEMP                            a6kb0pf8x0hqc         2028          4

SQL> select inst_id,tablespace,segtype,sum(blocks),count(*),sum(blocks)/count(*) from gv$tempseg_usage group by inst_id,tablespace,segtype;

   INST_ID TABLESPACE                      SEGTYPE   SUM(BLOCKS)   COUNT(*) SUM(BLOCKS)/COUNT(*)
---------- ------------------------------- --------- ----------- ---------- --------------------
         1 TEMP                            LOB_DATA         2176         17                  128
         2 TEMP                            LOB_DATA         1536         12                  128

Note:
上面持用tempfile rfile #7的会话是connect pool的长连接,在当前的数据库版本11.2.0.3(其实在9i-12c的版本都存在),持有的temp直到该session退出才会释放。如删除本案例中的tempfile rfile 7#,Rfile# 7的tempfile正在被实例1的sid=285的会话使用,kill 掉实例1的285会话即可删除7# tempfile。

并且当前2个实例上一共29个会话,占用的都是temp类型都是temp lob data.每个session占用1M(128*8k). 注意该视图中的SQL_ID并不一定是产生temp seg的SQL,而是该会话最后一次执行的SQL。

如何识别占用TEMP的SQL?

在11g中可以使用 V$ACTIVE_SESSION_HISTORY or DBA_HIST_ACTIVE_SESS_HISTORY的  TEMP_SPACE_ALLOCATED 列识别使用temp较大的查询SQL .在12C版本中v$tempseg_usage新增加列”SQL_ID_TEMPSEG”可以确认产生temp segment的SQLID.如下:

— 12.2

SQL> select username,session_num,sql_id,tablespace,CONTENTS,SEGTYPE,SEGRFNO#,BLOCKS,SQL_ID_TEMPSEG from v$tempseg_usage;
USERNAME SESSION_NUM SQL_ID        TABLESPACE     CONTENTS                      SEGTYPE    SEGRFNO#  BLOCKS    SQL_ID_TEMPSE
-------------------- -----------   ------------- ------------------------------ --------- --------- ---------- ---------------------
18783                g44b5rqw7xwq7 TEMP          TEMPORARY                      LOB_DATA          1        128         0w26sk6t6gq98

SQL> select sql_text from v$sqlarea where sql_id='0w26sk6t6gq98';

SQL_TEXT
--------------------------
SELECT XMLTYPE(DBMS_REPORT.GET_REPORT_WITH_SUMMARY(:B1 )) FROM DUAL

Note:

SQL_ID_TEMPSEG 是产生temp的SQL,XML 也是LOB一种形式。

— 11g

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

sys@DB11G 17:26:07> select distinct sid from v$mystat;

       SID
----------
       785

Elapsed: 00:00:00.01
sys@DB11G 17:26:26> SELECT TO_CLOB(LPAD('X',2000,'X')) FROM DUAL;

TO_CLOB(LPAD('X',2000,'X'))
--------------------------------------------------------------------------------
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX

sys@DB11G 2024-09-30 17:30:31> @temp

   INST_ID USERNAME                    SID    SERIAL# SQL_ID        TABLESPACE           CONTENTS  SEGTYPE           MB    EXTENTS     BLOCKS
---------- -------------------- ---------- ---------- ------------- -------------------- --------- --------- ---------- ---------- ----------
         1 ANBOB                       785       2631 9babjv8yq8ru3 TEMP                 TEMPORARY LOB_DATA           1          1        128

sys@DB11G 2024-09-30 17:30:33> @sqlid 9babjv8yq8ru3 
Show SQL text, child cursors and execution stats for SQLID 9babjv8yq8ru3 child %

HASH_VALUE PLAN_HASH_VALUE   CH# SQL_TEXT
---------- --------------- ----- ------------------------------------------------------------------------------------------------------------------------------------------------------
1029988163               0     0 BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
-- 这是一个错误的SQL ID,  可以使用x$ktsso 表

-- monitory temp REAL SQL  ID
SELECT  k.inst_id "INST_ID",
      ktssoses "SADDR",
      sid "SID",
      ktssosno "SERIAL#",
      username "USERNAME",
      osuser "OSUSER",
      ktssosqlid "SQL_ID",
      ktssotsn "TABLESPACE", decode(ktssocnt, 0, 'PERMANENT', 1, 'TEMPORARY') "CONTENTS",
      decode(ktssosegt, 1, 'SORT', 2, 'HASH', 3, 'DATA', 4, 'INDEX', 5, 'LOB_DATA', 6, 'LOB_INDEX' , 'UNDEFINED') "SEGTYPE",
      ktssofno "SEGFILE#", ktssobno "SEGBLK#", ktssoexts "EXTENTS", ktssoblks "BLOCKS", 
      round(ktssoblks*p.value/1024/1024, 2) "SIZE_MB", 
      ktssorfno "SEGRFNO#"
FROM x$ktsso k, v$session s, v$parameter p
WHERE ktssoses = s.saddr
    AND ktssosno = s.serial#
    AND p.name = 'db_block_size'order by sid;

	   INST_ID SADDR              SID    SERIAL# USERNAME                       OSUSER                         SQL_ID        TABLESPACE                      CONTENTS  SEGTYPE     SEGFILE#    SEGBLK#    EXTENTS     BLOCKS    SIZE_MB   SEGRFNO#
---------- ---------------- ---------- ---------- ------------------------------ ------------------------------ ------------- ------------------------------- --------- --------- ---------- ---------- ---------- ---------- ---------- ----------
         1 0000000088D37A80        785       2631 ANBOB                          oracle                         81q0rkt5nud7y TEMP                            TEMPORARY LOB_DATA         201        512          1        128          1          1

sys@DB11G 2024-09-30 17:27:51> @sqlid 81q0rkt5nud7y
Show SQL text, child cursors and execution stats for SQLID 81q0rkt5nud7y child %

HASH_VALUE PLAN_HASH_VALUE   CH# SQL_TEXT
---------- --------------- ----- ------------------------------------------------------------------------------------------------------------------------------------------------------
1263351038      1388734953     0 SELECT TO_CLOB(LPAD('X',2000,'X')) FROM DUAL

Note:
正在使用的temp可以使用x$ktsso 查询真实的SQL ID. 是to_clob产生的临时LOB TEMP SEGMENT.

60025 Event

从10.2.0.4提供了一个event 60025,当系统级或会话级启用了该event, 会在session中的temp lob不活动时(cache temp和nocache temp lobs都为0时),即使不退出会话也会自己释放空间供其它会话使用。如果启用了60025 event像下面这引起temp lob 会被释放掉:

SQL> select * from gv$temporary_lobs;

   INST_ID        SID CACHE_LOBS NOCACHE_LOBS ABSTRACT_LOBS
---------- ---------- ---------- ------------ -------------
         2       4806          0            0             0
         2       5159          0            0             0
         2       6843          0            0             0
         2       7975          0            0             0
         2       8192          0            0             0
         2      10728          0            0             0
         1          4          0            0             0
         1       1776          0            0             0
         1       3460          0            0             0
         1       4319          0            0             0
         1       4799          0            0             0
         1       4887          0            0             0
         1       8220          0            0             0
         1       8544          0            0             0
         1      10478          0            0             0
         1      11031          0            0             0
         1      11110          0            0             0
         1      11369          0            0             0
         1      12983          0            0             0
         1      14120          0            0             0
         1      17285          0            0             0
         1      17530          0            0             0
         1      17813          0            0             0
         1      17872          0            0             0

60025 event不可以动态在系统级修改生效,在spfile级修改重启生效;session级启用60025后,也不会立即释放之前的temp lobs.下面做个测试:

[oracle@weejar1:/home/oracle] ora

SQL*Plus: Release 11.2.0.3.0 Production on Wed Jan 17 14:27:24 2018
Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options


USERNAME             INST_NAME            HOST_NAME                 SID   SERIAL#  VERSION    STARTED  SPID            OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- ----- -------- ---------- -------- --------------- ----- --------------- ---------------- ----------------
SYS                  anbob1               weejar1                    17872 50597    11.2.0.3.0 20171114 19239           3327  19235           C0000016152D86D8 C000001652FD99F0

-ne 

SQL> declare
  2  b blob;
  3  begin
  4  dbms_lob.CREATETEMPORARY(b,true);
  5  dbms_lob.freeTEMPORARY(b);
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> select * from gv$temporary_lobs;

   INST_ID        SID CACHE_LOBS NOCACHE_LOBS ABSTRACT_LOBS
---------- ---------- ---------- ------------ -------------
...
         1      14120          0            0             0
         1      17285          0            0             0
         1      17530          0            0             0
         1      17813          0            0             0
         1      17872          0            0             0 

24 rows selected.

SQL> select u.inst_id,s.sid,s.status,tablespace,u.sql_id,segfile#,u.blocks,segfile#-p.value rfile from gv$tempseg_usage u,v$parameter p,gv$session s where u.session_addr = s.saddr AND u.inst_id = s.inst_id and p.NAME='db_files';

   INST_ID        SID STATUS   TABLESPACE                      SQL_ID            SEGFILE#     BLOCKS      RFILE
---------- ---------- -------- ------------------------------- --------------- ---------- ---------- ----------
         1      17872 INACTIVE TEMP1                           g0wf0fkkqwaya         2033        128          9
         1      17813 INACTIVE TEMP                            cbpmfx12jzj4r         2025        128          1
...

SQL> alter session set events '60025 trace name context forever';
Session altered.

SQL> select u.inst_id,s.sid,s.status,tablespace,u.sql_id,segfile#,u.blocks,segfile#-p.value rfile from gv$tempseg_usage u,v$parameter p,gv$session s where u.session_addr = s.saddr AND u.inst_id = s.inst_id and p.NAME='db_files';

   INST_ID        SID STATUS   TABLESPACE                      SQL_ID            SEGFILE#     BLOCKS      RFILE
---------- ---------- -------- ------------------------------- --------------- ---------- ---------- ----------
         1      17872 INACTIVE TEMP1                           g0wf0fkkqwaya         2033        128          9
         1      17813 INACTIVE TEMP                            cbpmfx12jzj4r         2025        128          1
...

SQL> declare
  2  b blob;
  3  begin
  4  dbms_lob.CREATETEMPORARY(b,true);
  5  end;
  6  /

PL/SQL procedure successfully completed.

SQL> select * from gv$temporary_lobs;
-- sid 17872 released

Note:
因为temp seg同会话可以reuse, 再配置了60025 event后,再次执行lob操作后, temp lob自动清理。

系统级修改

alter system set event='60025 trace name context forever' scope=spfile;

对于已存在的会话可以使用oradebug 启用指定sid

oradebug setorapid <oracle pid>
oradebug event 60025 trace name context forever
-- wait the session next call lob to clean temp lob by itself

为什么当使用连接池时,TEMP SPACE从不释放,即使配置了60025 event?

Tempory LOB segment in TEMP tablespace keep increaseing when customer uses CONNECTION POOL (Doc ID 2297060.1)

A Temp LOB was created when any SQL statement (or PLSQL statement) was executed on a Session.After that, the corresponding session is returned to the connection pool after completion of the execution of the corresponding SQL statement.However, because the session exit has not occurred, the Temp LOB used by the session still remains and is not released.

If the session is reassigned and new SQL statements that generate Temp LOBs are executed, the existing Temp LOB is not reused and new Temp LOB segments are created and used.
The temp LOB grows as the same cycle repeats over several sessions.In this situation, Temp LOBs used in a specific session must be freed explicitly at the application level in order for the same session to reuse it.

According to Bug 5723140,since 9i onwards we have been using only one temp segment for temp lobs in a session and all these temp lobs share the same temp segment. When there is a request to cleanup those temp lobs we do free space from temp tablespace and the same session can reuse it, but the temp segment is not released which means it is not available for use to other sessions. The actual cleanup happens only on session exit thru the callback that was registered for this purpose. Hence multiple sessions using temp lobs will have these temp segments active though unused, thus leading to temp segment growth.

正如note中描述的从9i以后,session使用一个临时段存在所有temp lobs,但是用完后free空间,同一会话可以reuse, 临时段只有到exit时才会释放,否则一直占用。如果session 使用了connect pool连接池的长连接,在完成相应 SQL 语句的执行后,相应会话将返回到连接池。但是,由于未发生会话退出,因此会话使用的临时 LOB 仍会保留,不会被释放。

如果重新分配(reassigned )会话并执行生成临时 LOB 的新 SQL 语句,则不会重用现有的临时 LOB,而是会创建和使用新的临时 LOB 段。随着同一循环在多个会话中重复,临时 LOB 会不断增长。在这种情况下,必须在应用程序级别明确释放特定会话中使用的临时 LOB,以便同一会话可以重用它。

所以即使配置了 Event 60025, 只要使用连接池,Temp LOB 也不会释放,因为 CACHE_LOB 存在(  both CACHE_LOB and NOCACHE_LOB values must be zero)如下:

SQL> select * from GV$TEMPORARY_LOBS;

INST_ID SID CACHE_LOBS NOCACHE_LOBS ABSTRACT_LOBS
------- --- ---------- ------------ -------------
 1        9      38179            0            0
 1       16       9230            0            0

 

我们发现的一些问题示例:

  1. Oracle TEMP 表空间在 Oracle 11g 和 12c 上持续增加
  2. Web Logic 连接池中的会话未清除 TEMP 表空间
  3. 使用 HikariCP,TEMP 表空间中的临时 LOB 段不断增加

 

解决方案

–10.2.0.4 and above

alter session set events '60025 trace name context forever'
  • DBMS_LOB.FREETEMPORARY
    如果使用连接池时未发生会话退出,则必须通过在创建段的会话的应用程序上调用 DBMS_LOB 上的 FREETEMPORARY 或 OCI 上的 OCIDurationEnd 来明确清理生成的临时 lob。
declare
  clb clob;
  ch varchar2(32767);
  k number;
begin
  dbms_lob.createtemporary(clb,true,dbms_lob.call);
    for i in 1..1500 loop
      ch:=lpad('o',32767,'Y');
      dbms_lob.writeappend(clb,length(ch),ch);
    end loop;
    k:=dbms_lob.getlength(clb);
    dbms_lob.freetemporary(clb);
    dbms_output.put_line('the clob length: '||k);
end;
/
  • connect pool or jdbc 配置

或建议设置connect pool一个更低的maxLifetime值Exiting the session,取决于应用程序中临时 LOB 的创建率,临时存储直到发生“会话退出”才会被释放。只有当连接从池中退出时才会发生“会话退出”。

修正 JDBC 错误configuration,数据库连接数远低于 Tomcat 最大线程数。这将使数据库会话保持打开状态,以便处理更多请求。这些会话将保存 TEMP 表空间中的对象,如果您已经在使用 Hibernate JDBC 配置,请将其更改为 Tomcat 级别的 JDBC 数据源

  • Java  code
import java.sql.*;

import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleResultSet;
import oracle.jdbc.OracleTypes;
import oracle.jdbc.pool.OracleDataSource;

import java.sql.NClob;


public class Class2 {
public static void main(String[] args) throws Exception {
String SQL1_syntax = "select to_nclob('a') from dual";
String SQL2_syntax = "select * from v$tempseg_usage";
String SQL3_syntax = "select count(*) from v$tempseg_usage";
String SQL4_syntax = "alter session set events '60025 trace name context forever'";

Connection conn = getConnection();

// event 60025 - if there are no active temp lobs in the session (ie: both cache temp lob and
// no-cache temp lobs used are zero) then the temp segment itself will also be freed
Statement stmt = conn.createStatement();
System.out.println(SQL4_syntax);
stmt.executeUpdate(SQL4_syntax);

System.out.println(SQL1_syntax);
ResultSet rs = stmt.executeQuery(SQL1_syntax);
NClob nclob;
rs.next();
System.out.println(rs.getString(1));
nclob = (NClob) ((OracleResultSet) rs).getNClob(1); /* we now have handle to the LOB memory */

System.out.println(SQL2_syntax);
rs = stmt.executeQuery(SQL2_syntax);
while(rs.next()) {
System.out.println(rs.getString(1) + " " + rs.getString(2) + " " + rs.getString(3) + " " + rs.getString(4) + " " + rs.getString(5) + " " + rs.getString(6) + " " + rs.getString(7) + " " + rs.getString(8));
}


// System.out.println("disconnect"); // We are NOT disconnecting
// conn.close();
// conn = getConnection();

 nclob.free();


// this block does the same as  nclob.free()
//OracleCallableStatement cs = (OracleCallableStatement) conn.prepareCall("begin DBMS_LOB.FREETEMPORARY ( ? ); end;");
//cs.registerOutParameter(1, OracleTypes.nclob);
//cs.setnclob(1, nclob);
//cs.execute();


stmt = conn.createStatement();
System.out.println(SQL2_syntax);
rs = stmt.executeQuery(SQL2_syntax);
while(rs.next()) {
System.out.println(rs.getString(1) + " " + rs.getString(2) + " " + rs.getString(3) + " " + rs.getString(4) + " " + rs.getString(5) + " " + rs.getString(6) + " " + rs.getString(7) + " " + rs.getString(8));
}
ResultSetMetaData rsmd = rs.getMetaData();
rs = stmt.executeQuery(SQL3_syntax);
rs.next();
// if # of rows is zero, this means temp segments have been released
System.out.println("Nb of rows : " + rs.getString(1));

}

public static Connection getConnection() throws SQLException {
String username = "<USERNAME>";
String password = "<PASSWORD>";
String thinConn = "jdbc:oracle:thin:@//<HOST>:<PORT>/<SERVICE>";
OracleDataSource ods = new OracleDataSource();
ods.setUser(username);
ods.setPassword(password);
ods.setURL(thinConn);
Connection conn = ods.getConnection();
DatabaseMetaData dbmd = conn.getMetaData();
System.out.println(dbmd.getDatabaseProductVersion());
System.out.println(dbmd.getDriverVersion());
conn.setAutoCommit(false);
return conn;
}
}


there are 2 equivalent ways of coding the release of the LOB resources.

  1. java.sql.NClob.free()
  2. (OracleCallableStatement) conn.prepareCall(“begin DBMS_LOB.FREETEMPORARY ( ? ); end;”);

总结

temp表空间的使用率并不同于datafile,当使用lob或一些SQL时可能会产生临时的lob_data, 该空间不会释放,同一个session中可以复用,直到会话退出,配置event 60025可以在会话退出前,主动释放lob temp, 但是要求当前session使用temp lob不活动时(cache temp和nocache temp lobs都为0时), 当应用程序使用了connect pool,session可能会因为cached lob无法释放,即使配置了event 60025, 此时需要应用显示的释放清理临时lob。

References
Tempory LOB segment in TEMP tablespace keep increaseing when customer uses CONNECTION POOL (Doc ID 2297060.1)
How to Release the Temp LOB Space and Avoid Hitting ORA-1652 (Doc ID 802897.1)
How to Release Temporary LOB Segments without Closing the JDBC Connection (Doc ID 1384829.1)
http://175.178.24.119/21c/content/adlob/temporary-LOB-APIs-in-different-programmatic-interfaces.html#GUID-67D95488-6B13-4941-9D13-5D1CB4F3D87C

打赏

, ,

对不起,这篇文章暂时关闭评论。