oracle 處理temp 表空間爆長的問題

oracle 處理temp 表空間爆長的問題  

2008-08-19 11:59:38|  分類: 數據庫 |  標籤:temp  oracle   |字號 訂閱

 

 

首先看temp ts,以下操作會使用temp表空間:

- build index.

- ORDER BY or GROUP BY

- DISTINCT.

- UNION & INTERSECT & MINUS

- Sort-Merge joins.

- Analyze

正常來說,在完成Select語句、create index等一些使用TEMP表空間的排序操作後,Oracle是會自動釋放掉臨時段a的。

但有些有侯我們則會遇到臨時段沒有被釋放,TEMP表空間幾乎滿的狀況,甚至是我們重啓了數據庫仍沒有解決問題

v$sort_segment字典中,我們可能看到temp的詳細的使用情況,

SQL> desc v$sort_segment

 名稱                                                  是否爲空? 類型

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

 TABLESPACE_NAME                                                VARCHAR2(31)

 SEGMENT_FILE                                                   NUMBER

 SEGMENT_BLOCK                                                  NUMBER

 EXTENT_SIZE                                                    NUMBER

 CURRENT_USERS                                                  NUMBER

 TOTAL_EXTENTS                                                  NUMBER

 TOTAL_BLOCKS                                                   NUMBER

 USED_EXTENTS                                                   NUMBER

 USED_BLOCKS                                                    NUMBER

 FREE_EXTENTS                                                   NUMBER

 FREE_BLOCKS                                                    NUMBER

 ADDED_EXTENTS                                                  NUMBER

 EXTENT_HITS                                                    NUMBER

 FREED_EXTENTS                                                  NUMBER

 FREE_REQUESTS                                                  NUMBER

 MAX_SIZE                                                       NUMBER

 MAX_BLOCKS                                                     NUMBER

 MAX_USED_SIZE                                                  NUMBER

 MAX_USED_BLOCKS                                                NUMBER

 MAX_SORT_SIZE                                                  NUMBER

 MAX_SORT_BLOCKS                                                NUMBER

 RELATIVE_FNO                                                   NUMBER

 

v$sort_usage將會提供目前操作的會話.

SQL> desc v$sort_usage;

 名稱                                                  是否爲空? 類型

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

 USERNAME                                                       VARCHAR2(30)

 USER                                                           VARCHAR2(30)

 SESSION_ADDR                                                   RAW(4)

 SESSION_NUM                                                    NUMBER

 SQLADDR                                                        RAW(4)

 SQLHASH                                                        NUMBER

 TABLESPACE                                                     VARCHAR2(31)

 CONTENTS                                                       VARCHAR2(9)

 SEGTYPE                                                        VARCHAR2(9)

 SEGFILE#                                                       NUMBER

 SEGBLK#                                                        NUMBER

 EXTENTS                                                        NUMBER

 BLOCKS                                                         NUMBER

 SEGRFNO#                                                       NUMBER

 

sql>select tablespace_name,current_users,total_blocks,used_blocks,free_blocks from v$sort_segment;

TABLESPACE_NAME   CURRENT_USERS TOTAL_BLOCKS USED_BLOCKS FREE_BLOCKS

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

TEMP              1        13696       13440         256

 

SQL> /

TABLESPACE_NAME  CURRENT_USERS TOTAL_BLOCKS USED_BLOCKS FREE_BLOCKS

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

TEMP              1        13696       13696           0

 

SQL> select username,session_addr,sqladdr,sqlhash,tablespace from v$sort_usage;

 

USERNAME   SESSION_ SQLADDR     SQLHASH TABLESPACE

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

SYS        682102D8 66BE52D8  919180126 TEMP

 

更多的信息如下:

 

col tablespace format a20

select se.username,se.sid,se.serial#,su.extents,su.blocks*to_number(rtrim(p.value)) as Space,tablespace,segtype,sql_text from v$sort_usage su,v$parameter p,v$session se,v$sql s

where p.name='db_block_size' and su.session_addr=se.saddr and s.hash_value=su.sqlhash and s.address=su.sqladdr order by se.username,se.sid;

 

USERNAME          SID    SERIAL#    EXTENTS      SPACE TABLESPACE           SEGTYPE

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

SQL_TEXT

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

SYS                 9          5        107  112197632 TEMP                 SORT

select * from arbor.server_lookup where rownum<1000000 order by

bill_lname_find

一般來說,排序操作都很快,由於本例是測試,所以temp表空間已經撐爆了,結果還沒有出來,所以可以抓到相應的sql

而這時候,在另一個會話中,我的查詢語句已經結束了,但是沒有返回任何結果!

 

 

metalink推薦下列一些方法:

--重啓實例

 重啓實例重啓時,smon進程對臨時段釋放,但是對於生產庫,我們就不能用這種方法了。。。。

如果重啓後sort段沒有被釋放呢?

--修改參數(僅適用於8i8i以下版本)

 SQL>alter tablespace temp increase 1;

 SQL>alter tablespace temp increase 0;

--合併碎片(僅適用於字典管理的表空間)

1、首先看誰在用臨時段

SELECT se.username,

       sid,

       serial#,

       sql_address,

       machine,

       program,

       tablespace,

       segtype,

       contents

  FROM v$session se,

       v$sort_usage su

WHERE se.saddr=su.session_addr;     

 

USERNAME          SID    SERIAL# SQL_ADDR MACHINE              PROGRAM                               TABLESPACE

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

SYS                 9          3 66CDF6D0 ASPIRE\GZ-ZHAOLEHUAN sqlplus.exe                           TEMP

 

 

2、然後將那些會話Kill

Alter system kill session 'sid,serial#';

SQL> alter system kill session '9,3';

系統已更改。

3、整理下表空間

Alter tablespace TEMP coalesce

*

ERROR 位於第 1 :

ORA-03217: 變更 TEMPORARY TABLESPACE 無效的選項

而事實上,這處方法只能針對字典管理的表空間。對於本地管理的表空間,不是需要整理的。

 

--診斷事件

select ts#, name from sys.ts$ ;

 

       TS# NAME

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

         0 SYSTEM

         1 UNDOTBS1

         2 TEMP

         3 CWMLITE

         4 DRSYS

         5 EXAMPLE

         6 INDX

         7 ODM

         8 TOOLS

         9 USERS

        10 XDB

        11 CAT_CUST

        12 CAT_CUST_IDX

        13 zlh_test

        14 ZLH_TEST

        15 TEMP1

已選擇16行。

 SQL>alter session set events 'immediate trace name DROP_SEGMENTS level 4'

 說明:level=TS#+ 1

--重建temp

1.創建中轉臨時表空間

create temporary tablespace  TEMP1 TEMPFILE 'E:\ORACLE\ORADATA\ORCL9\temp02.DBF' SIZE 512M REUSE AUTOEXTEND ON NEXT  1M MAXSIZE UNLIMITED;  

2.改變缺省臨時表空間爲剛剛創建的新臨時表空間temp1

alter database default  temporary tablespace  temp1;

3.刪除原來臨時表空間

drop tablespace temp including contents and datafiles;

4.重新創建臨時表空間

create temporary tablespace  TEMP TEMPFILE 'E:\ORACLE\ORADATA\ORCL9\temp01.DBF' SIZE 512M REUSE AUTOEXTEND ON NEXT  1M MAXSIZE UNLIMITED;  

5.重置缺省臨時表空間爲新建的temp表空間

alter database default  temporary tablespace  temp;

6.刪除中轉用臨時表空間

drop tablespace temp1 including contents and datafiles;

7.如果有必要,那麼重新指定用戶表空間爲重建的臨時表空間

alter user arbor temporary tablespace  temp; 

 

 

當然,以上方法,是因爲表空間撐爆了,我們纔去採用解決辦法,但最根本的原因還是在於disksort過多,而disk sort過多也可能是因爲

sort area的設置有問題。不過,從memorydisk的空間上來考慮,如果因爲disk sort而導致temp的空間增長太快,最應該注意的是到底是什麼樣的sql語句要使用這麼多的temp空間?

 

對於sort area設置,不在本文討論的範圍,轉帖網上別人總結的如下:

http://space.itpub.net/?uid-8720638-action-viewspace-itemid-364724

原始出處已不可考。。。。。

 

排序區域的分配

-專用服務器分配sort area.

 排序區域在PGA.

-共享服務器分配sort area.

 排序區域在UGA. (UGAshared pool中分配).

 

9i以前的版本,sort_area_size決定sort area的分配,9i及以後的版本,

workarea_size_policyauto,pga_aggregate_target參數決定sort

area的大於,這時的sort area應該是pga總內存的5%.workarea_size_policy

manual,sort area的大小還是於sort_area_size決定.

 

無論是那個版本,如果sort area開得過小,In-memory Sort率較低,temp表空間

肯定會增長得很快,如果開得較高,C/S結構中將會導致內存消耗嚴重(長連接較多).

 

由於smon進程每隔5分鐘都要對不再使用的sort segment進行回收,如果你不想讓

smon回收sort segment的話,可以使用以下兩個event寫入初始化參數文件,然後

重啓實例,這樣如果你的磁盤排序較多,很快就會漲暴磁盤......

 

event="10061 trace name context forever, level 10"  //禁止加收

event="10269 trace name context forever, level 10"  //禁止合併碎片

 

通過合理地設置pgasort_area_size,可以消除大部分的dist sort,那其它的disk

sort該如何處理呢?從sort引起的原因來看,索引/分析/異常引起的disk sort應該是

很少的一部分,其它的應該是select中的distinct/union/group by/order by以及

merge sort join,那我們如何捕獲這些操作呢?

通常如何有磁盤排序的SQL,它的邏輯讀/物理讀/排序/執行時間等都是比較大的,所以我

們可以對v$sqlareav$sql字典進行過濾,經過長期地監控數據庫,相信可以把這些害

羣之馬找出來.即然找出這些引起disk sortSQL後怎麼辦呢?當然是對SQL進行分析,

盡而優化之。

 

#!/bin/sh

ORACLE_SID=miat1cat;

export ORACLE_SID

sqlplus /nolog <<EOF

conn /as sysdba

col sql_text format a81

col disk_reads format 999999.99

col bgets_per format 99999999.99

col "ELAPSD_TIME(s)" format 9999.99

col "cpu_time(s)" format 9999.99

set long 99999999999

set pagesize 9999

select address,hash_value,disk_reads/executions disk_reads,elapsed_time/1000000/executions as "ELAPSD_TIME(s)",

       buffer_gets/executions bgets_per,executions,first_load_time as first_time,sql_text

 from v$sql

where executions > 0 and (disk_reads/executions > 500 or buffer_gets/executions > 20000) and command_type = 3

 order by 3,4;

 

--select s.disk_reads,s.buffer_gets/s.executions bgets_per,first_load_time,st.sql_text

-- from v$sql s,v$sqltext_with_newlines st

--where s.address=st.address and s.hash_value=st.hash_value

-- and s.disk_reads > 1000 or (s.executions > 0 and s.buffer_gets/s.executions > 50000)

--order by st.piece;

exit

EOF

 

用以下語句查看錶空間的使用情況:

也可以用如下的語句:

 

 

------查看所有表空間大小及使用情況

SELECT d.status "Status",

       d.tablespace_name "Name",

       d.contents "Type",

       d.extent_management "Extent Management",

       to_char(nvl(a.bytes / 1024 / 1024, 0), '99999999.999') "Total Size (M)",

       to_char(nvl(a.bytes - nvl(f.bytes, 0), 0) / 1024 / 1024,

               '99999999.999') "Used (M)",

       to_char(nvl(nvl(f.bytes, 0), 0) / 1024 / 1024, '99999999.999') "Free (M)",

       to_char(nvl((a.bytes - nvl(f.bytes, 0)) / a.bytes * 100, 0),

               '990.00') "Used %"

  FROM sys.dba_tablespaces d,

       (SELECT tablespace_name, SUM(bytes) bytes

          FROM dba_data_files

         GROUP BY tablespace_name) a,

       (SELECT tablespace_name, SUM(bytes) bytes

          FROM dba_free_space

         GROUP BY tablespace_name) f

 WHERE d.tablespace_name = a.tablespace_name(+)

   AND d.tablespace_name = f.tablespace_name(+);

 

 

Status    Name     Type   Extent Man Total Size (M Used (M)      Free (M)   Used %

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

ONLINE    BMIS_DATA                      PERMANENT LOCAL           2046.000         1.000      2045.000    0.05

ONLINE    CPAS_DATA                      PERMANENT LOCAL           1023.000       227.500       795.500   22.24

ONLINE    INDX     PERMANENT LOCAL                        255.000          .063       254.938    0.02

ONLINE    MOMAX_DATA                     PERMANENT LOCAL          13296.000     10785.500      2510.500   81.12

ONLINE    MOPORTAL_DATA                  PERMANENT LOCAL           2046.000       733.063      1312.938   35.83

ONLINE    MPAS_DATA                      PERMANENT LOCAL           3069.000       105.000      2964.000    3.42

ONLINE    SMAIL_DATA                     PERMANENT LOCAL           1023.000         7.688      1015.313    0.75

ONLINE    SYSTEM                         PERMANENT LOCAL           1023.000       347.375       675.625   33.96

ONLINE    TOOLS                          PERMANENT LOCAL           1271.000       123.063      1147.938    9.68

ONLINE    UNDOTBS1                       UNDO      LOCAL           9207.000      2355.313      6851.688   25.58

ONLINE    USERS                          PERMANENT LOCAL            255.000        15.625       239.375    6.13

ONLINE    TEMP                           TEMPORARY LOCAL               .000          .000          .000    0.00

11 rows selected.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章