delete大批量數據引發空間爆滿處理

前一天晚上作大表刪除操做測試,分段刪除,沒刪除100000條commit一次,因爲存儲過程打印了執行時間中途斷網,沒法看到執行時間
因而直接kill了任務
結果早上登陸測試數據庫發現空間爆滿
而後一時糊塗去弄了表的shrink跟dbms_stats.gather_table_stats想着收縮表釋放空間
弄到一半忽然想起,表的收縮最可能是釋放表空間的空閒空間,並不是系統空間
後來想一想,大量刪除反覆操做過程引起了undo的擴展,後來檢查表空間後確實如此
最後在線更換undo tablespace後刪除原tablespace後恢復

附上存儲過程sql

 create or replace procedure delete_table as
 i number(15);
 l_start number default dbms_utility.get_time;
 begin
    dbms_output.put_line('begin time:'||to_char(SYSTIMESTAMP,'HH24:MI:SS:FF2'));
    i:=0;
    for x in (select log_id from user_log where user_log_id<46380000)  
    loop
    delete from user_log where user_log_id = x.user_log_id;
    i:=i+1;
    if (i>10000) then
        begin
            --dbms_output.put_line('delete ok.'||i);
            commit;   
            i:=0;  
        end;    
    end if;  
    end loop;
    commit;
    dbms_output.put_line('ok.end time:'||to_char(SYSTIMESTAMP,'HH24:MI:SS:FF2'));
    exception when others then
    rollback;
end;
 /
delete_table

另外調試時記得 set serveroutput on數據庫

遇到的報錯提示

centos

[oracle@centos5 osa]$ dba

SQL*Plus: Release 10.2.0.4.0 - Production on Fri Jun 21 09:23:18 2013

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

ERROR:
ORA-09817: Write to audit file failed.
Linux-x86_64 Error: 28: No space left on device
ORA-01075: you are currently logged on


Enter user-name:
ERROR:
ORA-01017: invalid username/password; logon denied


Enter user-name:
ERROR:
ORA-01017: invalid username/password; logon denied


SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus

檢查磁盤空間,爆滿oracle

[oracle@centos5 osa]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              93G   89G     0 100% /
/dev/sda1              99M   12M   82M  13% /boot
tmpfs                1006M     0 1006M   0% /dev/shm

想着收縮下大表就有空間了,,,糊里糊塗開始shrink

ide

[oracle@centos5 osa]$ sqlplus test/test

SQL*Plus: Release 10.2.0.4.0 - Production on Fri Jun 21 09:23:26 2013

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


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

SQL> select table_name,BLOCKS,EMPTY_BLOCKS,NUM_ROWS  from user_tables where table_name = upper('user_log');

TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS
------------------------------ ---------- ------------ ----------
user_log                      2606643            0  176544060

SQL> alter table user_log enable row movement;

Table altered.

SQL> alter table user_log shrink space cascade;  --索引也能縮小
 
Table altered.

SQL> select table_name,BLOCKS,EMPTY_BLOCKS,NUM_ROWS  from user_tables where table_name = upper('user_log');

TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS
------------------------------ ---------- ------------ ----------
user_log                      2606643            0  176544060

SQL>

shrink後還須要從新收集統計信息,可是當空間爆滿時一樣沒法進行統計信息收集oop

SQL> exec dbms_stats.gather_table_stats('TEST','user_log');
BEGIN dbms_stats.gather_table_stats('TEST','user_log'); END;

*
ERROR at line 1:
ORA-01114: IO error writing block to file %s (block # %s)

想一想其實收縮、整理,只是釋放表空間的已用空間到空閒空間,並不會回收實際的磁盤測試

先刪除了一些自己在在根目錄下的oracle安裝文件才能夠作undo表空間的重建工做,不然沒空間仍是沒法工做

因爲大量操做致使了undo的自動擴展,佔用了大量空間,準備收縮undospa

[root@centos5 ~]# su - oracle
cd [oracle@centos5 ~]$ sqlplus test/test

SQL*Plus: Release 10.2.0.4.0 - Production on Fri Jun 21 11:39:40 2013

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


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

SQL> @space.sql

TABLESPACE_NAME      TOTAL       USED RATIO            FREE  MAX_BYTES
--------------- ---------- ---------- ---------- ---------- ----------
SYSTEM                 490     486.69   99.32          3.31       2.94
SYSAUX                 380        377   99.21             3        .81
TEST                 40960   20072.19   49.00      20887.81       3968
TS_OA                   50       5.06   10.12         44.94      39.94
USERS                    5        .44    8.80          4.56       4.56
TS_URP                 200       5.37    2.69        194.63     190.81
UNDOTBS1              9195     134.31    1.46       9060.69       2965
OSA_TEST               500       7.31    1.46        492.69     485.94
TS_IMPTEST              50        .06    0.12         49.94      49.94

9 rows selected.

SQL> select file_name,bytes/1024/1024 from dba_data_files where tablespace_name like 'UNDOTBS1';

FILE_NAME                                         BYTES/1024/1024
-----------------------------------        ----------------
/home/oracle/oradata/osa/undotbs01.dbf            9195

undo表空間的重建工做3d

--一、創建一個全新的undostb2
SQL>  create undo tablespace undotbs2 datafile '/home/oracle/oradata/osa/undotbs2.dbf' size 200M;

Tablespace created.

--二、修改系統的undo_tablespace爲undotbs2
SQL> alter system set undo_tablespace=undotbs2 scope=both;

System altered.
--三、刪除原有undo tablespace
SQL> drop tablespace undotbs1 including contents;

Tablespace dropped.
--四、刪除數據文件釋放空間
rm -rf /home/oracle/oradata/osa/undotbs01.dbf

再來看看空間調試

 

SQL> @space.sql              

TABLESPACE_NAME      TOTAL       USED RATIO            FREE  MAX_BYTES
--------------- ---------- ---------- ---------- ---------- ----------
SYSAUX                 380     377.94   99.46          2.06        .63
SYSTEM                 490     486.69   99.32          3.31       2.94
TEST                 40960   20072.19   49.00      20887.81       3968
TS_OA                   50       5.06   10.12         44.94      39.94
USERS                    5        .44    8.80          4.56       4.56
TS_URP                 200       5.37    2.69        194.63     190.81
OSA_TEST               500       7.31    1.46        492.69     485.94
UNDOTBS2               200       1.31    0.66        198.69     198.69
TS_IMPTEST              50        .06    0.12         49.94      49.94

再來收集統計信息查看下最高水位

SQL> select table_name,BLOCKS,EMPTY_BLOCKS,NUM_ROWS  from user_tables where table_name = upper('user_log');

TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS
------------------------------ ---------- ------------ ----------
user_log                      2606643            0  176544060

SQL>  exec dbms_stats.gather_table_stats('TEST','user_log');

PL/SQL procedure successfully completed.

SQL> select table_name,BLOCKS,EMPTY_BLOCKS,NUM_ROWS  from user_tables where table_name = upper('user_log');

TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS
------------------------------ ---------- ------------ ----------
user_log                      1719906            0  117470482    --shrink後統計信息更新了

若是是生產系統那會很慘,平常監控要很是注意數據庫空間、系統空間

相關文章
相關標籤/搜索