Oracle一次縮小表空間的處理過程
Oracle一次縮小表空間的處理過程
1 BLOG文件結構圖
2 前言部分
2.1 導讀和注意事項
各位技術愛好者,看完本文後,你可以掌握如下的技能,也可以學到一些其它你所不知道的知識,~O(∩_∩)O~:
① 收縮表空間的幾種辦法
② 表空間大小查詢
③ AIX下查詢磁碟空間大小的shell指令碼
④ 刪除資料檔案的正確方法
⑤ ORA-03262處理
⑥ 縮小資料檔案
⑦ su - grid asmcmd lsdg的使用
⑧ 其他常用命令
Tips:
① 本文在ITpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和微信公眾號(xiaomaimiaolhr)有同步更新
② 文章中用到的所有程式碼,相關軟體,相關資料請前往小麥苗的雲盤下載(http://blog.itpub.net/26736162/viewspace-1624453/)
③ 若文章程式碼格式有錯亂,推薦使用搜狗、360或QQ瀏覽器,也可以下載pdf格式的文件來檢視,pdf文件下載地址:http://blog.itpub.net/26736162/viewspace-1624453/,另外itpub格式顯示有問題,可以去部落格園地址閱讀
④ 本篇BLOG中命令的輸出部分需要特別關注的地方我都用灰色背景和粉紅色字型來表示,比如下邊的例子中,thread 1的最大歸檔日誌號為33,thread 2的最大歸檔日誌號為43是需要特別關注的地方;而命令一般使用黃色背景和紅色字型標注;對程式碼或程式碼輸出部分的注釋一般採用藍色字型表示。
List of Archived Logs in backup set 11
Thrd Seq Low SCN Low Time Next SCN Next Time
---- ------- ---------- ------------------- ---------- ---------
1 32 1621589 2015-05-29 11:09:52 1625242 2015-05-29 11:15:48
1 33 1625242 2015-05-29 11:15:48 1625293 2015-05-29 11:15:58
2 42 1613951 2015-05-29 10:41:18 1625245 2015-05-29 11:15:49
2 43 1625245 2015-05-29 11:15:49 1625253 2015-05-29 11:15:53
[ZHLHRDB1:root]:/>lsvg -o
T_XDESK_APP1_vg
rootvg
[ZHLHRDB1:root]:/>
00:27:22 SQL> alter tablespace idxtbs read write;
====》2097152*512/1024/1024/1024=1G
本文如有錯誤或不完善的地方請大家多多指正,ITPUB留言或QQ皆可,您的批評指正是我寫作的最大動力。
3 環境介紹
專案 |
source db |
db 型別 |
RAC |
db version |
11.2.0.3.0 |
db 儲存 |
ASM |
OS版本及kernel版本 |
AIX 64位 7.1.0.0 |
4 處理過程
一個同事過來說,表空間不夠了,讓我幫忙看看,好吧,首先看一下表空間的大小,SQL語句如下:
WITH wt1 AS
(SELECT ts.TABLESPACE_NAME,
df.all_bytes,
decode(df.TYPE,
'D',
nvl(fs.FREESIZ, 0),
'T',
df.all_bytes - nvl(fs.FREESIZ, 0)) FREESIZ,
df.MAXSIZ,
ts.BLOCK_SIZE,
ts.LOGGING,
ts.FORCE_LOGGING,
ts.CONTENTS,
ts.EXTENT_MANAGEMENT,
ts.SEGMENT_SPACE_MANAGEMENT,
ts.RETENTION,
ts.DEF_TAB_COMPRESSION,
df.ts_df_count
FROM dba_tablespaces ts,
(SELECT 'D' TYPE,
TABLESPACE_NAME,
COUNT(*) ts_df_count,
SUM(BYTES) all_bytes,
SUM(decode(MAXBYTES, 0, BYTES, MAXBYTES)) MAXSIZ
FROM dba_data_files d
GROUP BY TABLESPACE_NAME
UNION ALL
SELECT 'T',
TABLESPACE_NAME,
COUNT(*) ts_df_count,
SUM(BYTES) all_bytes,
SUM(decode(MAXBYTES, 0, BYTES, MAXBYTES))
FROM dba_temp_files d
GROUP BY TABLESPACE_NAME) df,
(SELECT TABLESPACE_NAME,
SUM(BYTES) FREESIZ
FROM dba_free_space
GROUP BY TABLESPACE_NAME
UNION ALL
SELECT tablespace_name,
SUM(d.BLOCK_SIZE * a.BLOCKS) bytes
FROM gv$sort_usage a,
dba_tablespaces d
WHERE a.tablespace = d.tablespace_name
GROUP BY tablespace_name) fs
WHERE ts.TABLESPACE_NAME = df.TABLESPACE_NAME
AND ts.TABLESPACE_NAME = fs.TABLESPACE_NAME(+))
SELECT (SELECT A.TS#
FROM V$TABLESPACE A
WHERE A.NAME = UPPER(t.TABLESPACE_NAME)) TS#,
t.TABLESPACE_NAME TS_Name,
round(t.all_bytes / 1024 / 1024) ts_size_M,
round(t.freesiz / 1024 / 1024) Free_Size_M,
round((t.all_bytes - t.FREESIZ) / 1024 / 1024) Used_Size_M,
round((t.all_bytes - t.FREESIZ) * 100 / t.all_bytes, 3) Used_per,
round(MAXSIZ / 1024 / 1024/1024, 3) MAX_Size_g,
round(decode(MAXSIZ, 0, to_number(NULL), (t.all_bytes - FREESIZ)) * 100 /
MAXSIZ,
3) USED_per_MAX,
round(t.BLOCK_SIZE) BLOCK_SIZE,
t.LOGGING,
t.ts_df_count
FROM wt1 t
UNION ALL
SELECT to_number('') TS#,
'ALL TS:' TS_Name,
round(SUM(t.all_bytes) / 1024 / 1024, 3) ts_size_M,
round(SUM(t.freesiz) / 1024 / 1024) Free_Size_m,
round(SUM(t.all_bytes - t.FREESIZ) / 1024 / 1024) Used_Size_M,
round(SUM(t.all_bytes - t.FREESIZ) * 100 / SUM(t.all_bytes), 3) Used_per,
round(SUM(MAXSIZ) / 1024 / 1024/1024) MAX_Size,
to_number('') "USED,% of MAX Size",
to_number('') BLOCK_SIZE,
'' LOGGING,
to_number('') ts_df_count
FROM wt1 t
order by TS#
;
TPCCIND表空間佔用了99%了,剩下378M,不夠用了,好吧,看看系統還有剩餘的空間沒有:
這個截圖的shell指令碼如下,可以在AIX環境下檢視磁碟的使用情況,作者曾花了接近2天的時間寫的(主要是不熟悉AWK,汗顏,,,):
[ZFLHRADB1:root]:/>more disk*
if [ 1 = 1 ] ;then
sum=0;asmnum=0
awk 'BEGIN {printf "------------------------------------------------------------------------------------------------------------------------------\n"; printf "%-43s %-18s %-14s %-8s %-15s %-14s\n","| disk ","| PVID ","| no_reserve ","| size(G)","| disktype ","| disk_storage |"; printf "------------------------------------------------------------------------------------------------------------------------------\n";}'
for diskname in `lspv | grep disk | awk '{print $1}'`;do
mydiskname=`ls -l /dev/rdiskname|grep?w/dev/r diskname| cut -c 1-12,17-38,59-76`
mydiskpvid=`lquerypv -H /dev/$diskname | cut -c 1-16`
if [ "${mydiskpvid}" = "" ];then mydiskpvid="0000000000000000" ; fi 2>/dev/null
mydiskreserve=`lsattr -El $diskname | grep -i reserve_policy | cut -c 17-30`
mydisksize=`bootinfo -s diskname2>/dev/null‘;let"mydisksize1= mydisksize/1024" 2>/dev/null
mydiskvg=`lspv | grep -w 3}'`
mydiskasmgroup=`lquerypv -h /dev/r NF}'|sed -e 's/\.//g' -e 's/\|//g' | awk '{ if (1!="")printf"+" 1 ; else print "NULL"}'`
mydiskflag=`lquerypv -h /dev/r$diskname 2>/dev/null|grep -i orcldisk|wc -l`
if [ mydisksize?lt1000];thenmydisktype="HeadDisk";elif[ {mydisksize} -gt 1000 -a mydiskflag?gt0];thenmydisktype="ASM:" mydiskasmgroup; elif [ mydisksize?gt1000?a {mydiskflag} -eq 0 -a mydiskvg!="None"];thenmydisktype= mydiskvg ; else mydisktype="Not_Used"; fi 2>/dev/null
mydiskpath=`lspath -l diskname2>/dev/null|head?1|awk′print$NF′|sed"s/. //"`
mydiskstring=`odmget -q attribute="unique_id" CuAt|egrep "name|value"|paste - -|tr '\t' ' '|grep -w ${diskname}|sed 's/\"//g'`
mydiskstorage=`echo NF ~ /EMC/) {print "EMC"} else if (NF /NETAPP/)print"NETAPP"elseif( NF ~ /HITACHI/) {print "HDS"}}'`
mydiskdepth=`lsattr -El 2}'`
mydiskstorage1=mydiskstorage"," mydiskpath","$mydiskdepth
[ mydisksize1?gt1?a {mydiskflag} -gt 0 ] && { (( sum=sum+mydisksize1));((asmnum= asmnum+1 )) ;}
echo "mydiskname"" mydiskpvid" "mydiskreserve"" {mydisksize1%.*}" "mydisktype"" mydiskstorage1" | awk '{printf "| %-10s %-6s %-8s %-14s | %-17s | %-12s | %-8s| %-15s | %-14s |\n",1, 2,3, 4,5, 6,7, 8,$9}'
done
awk 'BEGIN {printf "------------------------------------------------------------------------------------------------------------------------------\n";}'
echo "ASMDISK_TOTAL:asmnum""TOTALSIZE(GB): sum" |awk '{printf "| %-20s %-101s |\n", 1, 2}'
awk 'BEGIN {printf "------------------------------------------------------------------------------------------------------------------------------\n";}'
fi
if [ 1 = 1 ] ;then
sum=0;asmnum=0
awk 'BEGIN {printf "------------------------------------------------------------------------------------------------------------------------------\n"; printf "%-43s %-18s %-14s %-8s %-15s %-14s\n","| disk ","| PVID ","| no_reserve ","| size(G)","| disktype ","| disk_storage |"; printf "------------------------------------------------------------------------------------------------------------------------------\n";}'
for diskname in `lspv | grep disk | awk '{print diskname |grep -w /dev/rdiskname|cut?c1?12,17?38,59?76‘mydiskpvid=‘lquerypv?H/dev/ diskname | cut -c 1-16`
if [ "mydiskpvid"=""];thenmydiskpvid="0000000000000000";fi2>/dev/nullmydiskreserve=‘lsattr?El diskname | grep -i reserve_policy | cut -c 17-30`
mydisksize=`bootinfo -s diskname2>/dev/null‘;let"mydisksize1= mydisksize/1024" 2>/dev/null
mydiskvg=`lspv | grep -w diskname|awk′print$3′‘mydiskasmgroup=‘lquerypv?h/dev/r diskname|head -n 7|tail -n 1|awk -F ' ' '{print diskname 2>/dev/null|grep -i orcldisk|wc -l`
if [ mydisksize?lt1000];thenmydisktype="HeadDisk";elif[ {mydisksize} -gt 1000 -a mydiskflag?gt0];thenmydisktype="ASM:" mydiskasmgroup; elif [ mydisksize?gt1000?a {mydiskflag} -eq 0 -a mydiskvg!="None"];thenmydisktype= mydiskvg ; else mydisktype="Not_Used"; fi 2>/dev/null
mydiskpath=`lspath -l diskname2>/dev/null|head?1|awk′print$NF′|sed"s/. //"`
mydiskstring=`odmget -q attribute="unique_id" CuAt|egrep "name|value"|paste - -|tr '\t' ' '|grep -w diskname|sed′s/\"//g′‘mydiskstorage=‘echo {mydiskstring} 2> /dev/null|awk '{ if(NF /EMC/)print"EMC"elseif( NF ~ /NETAPP/) {print "NETAPP"} else if( {diskname}|grep queue_depth|awk '{print mydiskstorage","mydiskpath"," mydiskdepth
[ mydisksize1?gt1?a {mydiskflag} -gt 0 ] && { (( sum=sum+mydisksize1));((asmnum= asmnum+1 )) ;}
echo "mydiskname"" mydiskpvid" "mydiskreserve"" {mydisksize1%.*}" "mydisktype"" mydiskstorage1" | awk '{printf "| %-10s %-6s %-8s %-14s | %-17s | %-12s | %-8s| %-15s | %-14s |\n",1, 2,3, 4,5, 6,7, 8, asmnum" "TOTAL_SIZE(GB): 1,$2}'
awk 'BEGIN {printf "------------------------------------------------------------------------------------------------------------------------------\n";}'
fi
從截圖可以看出分配給資料庫的一共8塊磁碟,看看資料庫中有多少:
SELECT * FROM v$asm_disk;
那就只能隔東牆補西牆,看到系統裡TPCCHIS表空間剩下270G,經開發確認,可以縮小一些空間:
而縮小表空間有3種辦法:
1、ALTER TABLESPACE test SHRINK SPACE KEEP 20M; --主要針對臨時表空間
2、刪除資料檔案
3、縮小資料檔案的大小
我們試試第一種:ALTER TABLESPACE TPCCHIS SHRINK SPACE KEEP 100G;
ORA-12916: cannot shrink permanent or dictionary managed tablespace
報錯了,永久表空間或是字典管理的不能SHRINK,只能針對temp表空間進行SHRINK SPACE。
試試第二種辦法:刪除資料檔案
SELECT * FROM dba_data_files d WHERE d.tablespace_name='TPCCHIS';
SELECT D.HEADER_FILE, COUNT(1)
FROM DBA_SEGMENTS D
WHERE D.TABLESPACE_NAME = 'TPCCHIS'
GROUP BY D.HEADER_FILE;
所以,表都在23號檔案上,其它檔案應該可以刪掉的。
ALTER TABLESPACE TPCCHIS DROP DATAFILE 13;
結果報錯了:ORA-03262: the file is non-empty
[ZFLHRADB1:oracle]:/oracle>oerr ora 03262
03262, 00000, "the file is non-empty"
// *Cause: Trying to drop a non-empty datafile
// *Action: Cannot drop a non empty datafile
參考mos文章:
Unable to Drop a Datafile From the Tablespace Using Alter Tablespace Command (文件 ID 1050261.1)
違反下列任何一個條件,該datafile均不能被drop
1)必須為空,否則會報:ORA-03262: the file is non-empty。值得注意的是,non-empty的含義是有extent被分配給了table,而不是該table中有無rows,此時若是使用drop table xxx是不行的,必須使用 drop table xxx purge;或者在已經使用了drop table xxx的情況下,再使用purge table “xxx表在回收站中的名稱”來purge該表,否則空間還是不釋放,datafile依然drop不掉。
2)不能是所屬表空間的第一個file
以上兩者可以透過drop tablespace來達到目的。
3)不能在read-only表空間中。
4)不能被offline,否則會報:ORA-03264: cannot drop offline datafile of locally managed tablespace
針對該報錯,解決方法為:
[oracle@rhel6 u01]$ oerr ora 3264
03264, 00000, "cannot drop offline datafile of locally managed tablespace"
// *Cause: Trying to drop offline datafile in lmts
// *Action: Try to drop file afetr making it online
5) Cannot be a datafile that is part of the system tablespace, even if it is not the first datafile of the system tablespace --該條來源於How to Drop a Datafile From a Tablespace (文件 ID 111316.1)
試了試其它檔案還是不能刪除,好吧,這個必須把表移動到其它表空間後才可以,算了,比較麻煩。
試試第3種辦法:縮小資料檔案的大小
SELECT 'alter database datafile ' || D.FILE_ID || ' resize 1G;'
FROM DBA_DATA_FILES D
WHERE D.TABLESPACE_NAME = 'TPCCHIS';
按照開發的要求,縮減100G即可,所以,我們執行3個即可,每個檔案大小為30g,
alter database datafile 23 resize 1G;
alter database datafile 25 resize 1G;
alter database datafile 27 resize 1G;
執行完成之後,表空間大小:
空間多出100G:
我們可以給表空間TPCCIND加空間了:
ALTER TABLESPACE TPCCIND ADD DATAFILE '+DATA1' SIZE 30G;
ALTER TABLESPACE TPCCIND ADD DATAFILE '+DATA1' SIZE 30G;
ALTER TABLESPACE TPCCIND ADD DATAFILE '+DATA1' SIZE 30G;
增加完成後檢視錶空間大小:
好吧,可以了。
About Me
..........................................................................................................................................................................................................
● 本文作者:小麥苗,只專注於資料庫的技術,更注重技術的運用
● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新,推薦pdf檔案閱讀
● QQ群:230161599 微信群:私聊
● 本文itpub地址:http://blog.itpub.net/26736162/viewspace-2124606/ 部落格園地址:http://www.cnblogs.com/lhrbest/articles/5846969.html
● 本文pdf版: (提取碼:ed9b)
● 小麥苗分享的其它資料:http://blog.itpub.net/26736162/viewspace-1624453/
● 聯絡我請加QQ好友(642808185),註明新增緣由
● 於 2016-09-06 09:00~2016-09-06 20:00 在中行完成
● 【版權所有,文章允許轉載,但須以連結方式註明源地址,否則追究法律責任】
..........................................................................................................................................................................................................
長按識別二維碼或微信客戶端掃描下邊的二維碼來關注小麥苗的微信公眾號:xiaomaimiaolhr,學習最實用的資料庫技術。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2124606/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- undo表空間損壞的處理過程
- oracle臨時表空間過大的原因&&處理Oracle
- 記一次ORACLE的UNDO表空間爆滿分析過程Oracle
- oracle系統表空間過大問題處理Oracle
- oracle goldengate 目標端表空間滿導致程式abended處理過程OracleGo
- Oracle Temp臨時表空間處理Oracle
- oracle 表空間 不足時如何處理Oracle
- Oracle undo表空間爆滿的處理方法Oracle
- Oracle表空間收縮方案Oracle
- oracle中undo表空間丟失處理方法Oracle
- oracle sysaux表空間滿了處理辦法OracleUX
- undo表空間故障處理
- oracle之臨時表空間的收縮Oracle
- ORACLE資料庫壞塊的處理 (一次壞快處理過程)Oracle資料庫
- UNDO表空間損壞的處理
- oracle處理SQL的過程OracleSQL
- 一次臨時表空間大量佔用問題的處理
- oracle檢查 小表空間Oracle
- Oracle表空間小知識Oracle
- 收縮臨時表空間收縮方法及ORA-03297錯誤處理
- 【故障處理】一次RAC故障處理過程
- Check_oracle_health之表空間使用及處理Oracle
- 收縮表空間 for Oracle 10gOracle 10g
- undo 表空間滿了的處理方法
- 處理TEMP表空間滿的問題
- 分析表空間空閒率並收縮表空間
- undo表空間佔用磁碟空間滿案例處理
- 【RESIZE】Oracle收縮表空間主要命令Oracle
- 一次壞塊的處理過程(一)
- 一次壞塊的處理過程(二)
- 一次壞塊的處理過程 [轉]
- oracle空間收縮Oracle
- sysaux 表空間爆滿處理方法UX
- sysaux 表空間不足問題處理UX
- 測試表的空間壓縮與表空間的關係
- SYSAUX表空間佔用過大情況下的處理(AWR資訊過多)UX
- 索引表空間不足的幾個處理思路索引
- 【Oracle故障處理】-Oracle9i臨時表空間刪除重建Oracle