轉 oracle lob 對象怎么清理釋放空間


總結,如果碰到系統消耗lob 空間增長太快,那么如何對lob 對象進行清理,

lob 對象如何delete 沒辦法釋放空間,只有truncate 操作釋放空間,具體如下:

 

-》當然還有第三種方法;如下:但是沒測試過

 You can check other options like Shrinking LOBS / How to Shrink a Securefile LOB Using Online Redefinition (DBMS_REDEFINITION)? (Doc ID 1394613.1)

 

-》如果還需要另外一種方法https://blog.csdn.net/weixin_30192375/article/details/116435093

釋放lob類型數據占據的空間

alter table adu_* move tablespace BFPICK lob(content) store as (tablespace bfpick)

但是根據官方說法,這種方法也有可能導致ora-01555的報錯,也要經過充分測試

To BottomTo Bottom

 select chunk 
from dba_lobs
where table_name =upper('ContainsLOB_tab');
  2    3  
     CHUNK
----------
      8192

ALTER TABLE ContainsLOB_tab
MOVE LOB(c) STORE AS (
TABLESPACE users CHUNK 17000
);
/

SQL> select chunk 
from dba_lobs
where table_name =upper('ContainsLOB_tab');  2    3  

     CHUNK
----------
     24576

 PCTVERSION
 ~~~~~~~~~~
  "STORE AS ( PCTVERSION n )"

	PCTVERSION can be changed after creation using:
                ALTER TABLE tabname MODIFY LOB (lobname) ( PCTVERSION n );

	PCTVERSION affects the reclamation of old copies of LOB data.
	This affects the ability to perform consistent read.

	If a session is attempting to use an OLD version of a LOB
	and that version gets overwritten (because PCTVERSION is too small)
	then the user will typically see the errors:
		ORA-01555: snapshot too old: 
				rollback segment number  with name "" too small
		ORA-22924: snapshot too old

	PCTVERSION can prevent OLD pages being used and force the segment
	to extend instead. 

	Do not expect PCTVERSION to be an exact percentage of space as there 
	is an internal fudge factor applied.

 

 

 

 

->

 LOB space not getting released after Delete from TABLE commands when using Securefile / Basic File.

 Check If the Application code is using any of the Delete Commands if so you can check this.

SOLUTION

 This solution is applicable for columns with Basicfile / Securefile LOB storage.

 You can check other options like Shrinking LOBS / How to Shrink a Securefile LOB Using Online Redefinition (DBMS_REDEFINITION)? (Doc ID 1394613.1)

 This steps is to confirm that the Truncate only reclaim the space from Object , Block , Segment , Tablespace Level.

 

To BottomTo Bottom


SYMPTOMS

 LOB space Not Getting released

Note: be aware that the unused space after deletion can be reused in the LOB segment for further insert after retention time is passed.

CHANGES

 

CAUSE

 LOB space not getting released after Delete from TABLE commands when using Securefile / Basic File.

 Check If the Application code is using any of the Delete Commands if so you can check this.

SOLUTION

 This solution is applicable for columns with Basicfile / Securefile LOB storage.

 You can check other options like Shrinking LOBS / How to Shrink a Securefile LOB Using Online Redefinition (DBMS_REDEFINITION)? (Doc ID 1394613.1)

 This steps is to confirm that the Truncate only reclaim the space from Object , Block , Segment , Tablespace Level.

 

A) Tested in 12.2 ::

1) Create Database Objects in 12.2 to perform test case:

[test]/etc> sqlplus

SQL*Plus: Release 12.2.0.1.0 Production on Mon Jul 10 17:28:20 2017
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Enter user-name: sys as sysdba
Enter password:
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> select name,created from v$database;

NAME        CREATED
--------- -----------
XXX        10-JUL-17

SQL> CREATE SMALLFILE TABLESPACE "TTS_NAME" DATAFILE '/refresh/home/app/oracle/oradata/xxx/DB01.dbf' SIZE 3072M REUSE AUTOEXTEND ON NEXT 100M MAXSIZE 3072M LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;

Tablespace created.

SQL> create table lob_test (id number, data blob) tablespace "TTS_NAME";

Table created.

SQL> create sequence lob_test_seq;

Sequence created.

SQL> Create directory TEST as '/tmp/test';

Directory created.

SQL> grant read,write on directory TEST to sys;

Grant succeeded.

-- For this Test case you can use any Binary file ( dump ,zip file etc and rename to *.dat )

SQL> !ls -ltr *.dat

-rw-r--r-- 1 grdbms grdbms 4759552 Jul 10 16:21 test.dat

       

       

 

2) To check from Block Level free space create a Function:

SQL> create or replace function get_block_info
( p_segname in varchar2,
p_owner in varchar2 default user,
p_type in varchar2 default 'TABLE',
p_partition in varchar2 default NULL )
return number
authid current_user
as
l_total_blocks number;
l_total_bytes number;
l_unused_blocks number;
l_unused_bytes number;
l_LastUsedExtFileId number;
l_LastUsedExtBlockId number;
l_LAST_USED_BLOCK number;
begin
dbms_space.unused_space
2 ( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
3 partition_name => p_partition,
4 total_blocks => l_total_blocks,
total_bytes => l_total_bytes,
unused_blocks => l_unused_blocks,
5 unused_bytes => l_unused_bytes,
6 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
7 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
8 LAST_USED_BLOCK => l_LAST_USED_BLOCK );
9
10 11 return l_total_blocks || '.' || (l_total_blocks-l_unused_blocks);
exception
12 when others then return NULL;
end;
/

Function created.

 

 

3) Initially Check for Tablespace Space , Segment and block level Free space :

SQL> col "Tablespace" for a22

col "Used MB" for 99,999,999
col "Free MB" for 99,999,999
col "Total MB" for 99,999,999

select df.tablespace_name "Tablespace",
totalusedspace "Used MB",
(df.totalspace - tu.totalusedspace) "Free MB",
df.totalspace "Total MB",
round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace))
"Pct. Free"
from
(select tablespace_name,
round(sum(bytes) / 1048576) TotalSpace
from dba_data_files
group by tablespace_name) df,
(select round(sum(bytes)/(1024*1024)) totalusedspace, tablespace_name
from dba_segments
group by tablespace_name) tu
where df.tablespace_name = tu.tablespace_name ;

Tablespace                Used MB    Free MB    Total MB   Pct. Free
---------------------- ----------- ----------- ----------- ----------
TTS_NAME              264       2,808       3,072       91                ---->>  New Tablespace more than 90% free

 

-- After creating the Function use this Query to get from Block level

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST'
);

TABLE_NAME             TOTAL_BLOCKS        USED_BLOCKS
-------------       -----------------    -------------------
LOB_TEST                  8                     3                               ---->>  Free Blocks Available            

 

4) Start the sqlplus session from the *.dat file location

 

SQL> DECLARE
src_file BFILE := bfilename('TEST', 'test.dat');
dst_file BLOB;
lgh_file BINARY_INTEGER;
cur_id NUMBER(10);
BEGIN
FOR i IN 1..500                                                                                        ---->> Insert 1 to 500
LOOP
INSERT INTO lob_test(id,data) VALUES(lob_test_seq.nextval,empty_blob())
RETURNING id into cur_id;
-- lock record
SELECT data INTO dst_file FROM lob_test WHERE id=cur_id FOR UPDATE;

dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
lgh_file := dbms_lob.getlength(src_file);
dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
dbms_lob.fileclose(src_file);
END LOOP;
END;
/

PL/SQL procedure successfully completed.

SQL> select sum(dbms_lob.getchunksize(data))/1024/1024 from lob_test;

SUM(DBMS_LOB.GETCHUNKSIZE(DATA))/1024/1024
------------------------------------------------------------
4.22763824

SQL> SELECT owner||'.'||SEGMENT_NAME NAME, SEGMENT_TYPE TYPE,
EXTENTS, MAX_EXTENTS, MAX_EXTENTS - EXTENTS LEFT_EXTENTS,
NEXT_EXTENT/1024 next_kb, bytes/1024 bytes_kb
FROM DBA_SEGMENTS
WHERE tablespace_name = 'TTS_NAME' ;

NAME                             TYPE              EXTENTS      MAX_EXTENTS   LEFT_EXTENTS  NEXT_KB   BYTES_KB
-----------------------        --------------- --------------- ------------  -------------  -------- ---------- 
SYS.LOB_TEST                    TABLE               1          2147483645     2147483644      1024        64
SYS.SYS_IL0000073541C00002$$    LOBINDEX            1          2147483645     2147483644      1024        64
SYS.SYS_LOB0000073541C00002$$   LOBSEGMENT          212        2147483645     2147483433      1024        2752704

SQL> DECLARE
src_file BFILE := bfilename('TEST', 'test.dat');
dst_file BLOB;
lgh_file BINARY_INTEGER;
cur_id NUMBER(10);
BEGIN
FOR i IN 1..500
LOOP
INSERT INTO lob_test(id,data) VALUES(lob_test_seq.nextval,empty_blob())
RETURNING id into cur_id;
-- lock record
SELECT data INTO dst_file FROM lob_test WHERE id=cur_id FOR UPDATE;

dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
lgh_file := dbms_lob.getlength(src_file);
dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
dbms_lob.fileclose(src_file);
END LOOP;
END;

/
DECLARE
*
ERROR at line 1:
ORA-01691: unable to extend lob segment SYS.SYS_LOB0000073541C00002$$ by 1024 in tablespace TTS_NAME ---->> Errored out
ORA-06512: at "SYS.DBMS_LOB", line 945
ORA-06512: at line 16

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST'
);

TABLE_NAME        TOTAL_BLOCKS     USED_BLOCKS
-------------------------------  --------------------
LOB_TEST                8                8                                          ---->> Fully Occupied

Tablespace              Used MB    Free MB   Total MB  Pct. Free
---------------------- ----------- -------- ---------  --------------

TTS_NAME          3,070         2      3,072         0                       ---->> Errored out because of no free space ( as expected )

 

SQL> SELECT owner||'.'||SEGMENT_NAME NAME, SEGMENT_TYPE TYPE,
EXTENTS, MAX_EXTENTS, MAX_EXTENTS - EXTENTS LEFT_EXTENTS,
NEXT_EXTENT/1024 next_kb, bytes/1024 bytes_kb
FROM DBA_SEGMENTS
WHERE tablespace_name = 'TTS_NAME' ;

NAME                                              TYPE            EXTENTS   MAX_EXTENTS   LEFT_EXTENTS NEXT_KB BYTES_KB
------------------------------                 ------------------ ---------- ----------- ------------ -----------------------
SYS.LOB_TEST                                       TABLE            1         2147483645   2147483644     1024    64
SYS.SYS_IL0000073541C00002$$                       LOBINDEX         1         2147483645   2147483644     1024    64
SYS.SYS_LOB0000073541C00002$$                      LOBSEGMENT       230       2147483645   2147483415     1024    3143872

 

5) Now after the Space Error Use Delete , but Delete Will not reclaim any space from Object / Block level :

SQL> delete from lob_test;                         

550 rows deleted.

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST'
);

TABLE_NAME             TOTAL_BLOCKS       USED_BLOCKS
-------------     ------------------    ---------------------
LOB_TEST                       8               8                           ---->> Delete will not reclaim Space

 

Tablespace                Used MB    Free MB     Total MB   Pct. Free
---------------------- ----------- ----------- ----------- ----------
TTS_NAME             3,070       2         3,072         0           ---->> Actual issue is "Delete from table not working"

 

SQL> SELECT owner||'.'||SEGMENT_NAME NAME, SEGMENT_TYPE TYPE,
EXTENTS, MAX_EXTENTS, MAX_EXTENTS - EXTENTS LEFT_EXTENTS,
NEXT_EXTENT/1024 next_kb, bytes/1024 bytes_kb
FROM DBA_SEGMENTS
WHERE tablespace_name = 'TTS_NAME' ; 

NAME                           TYPE                EXTENTS   MAX_EXTENTS LEFT_EXTENTS NEXT_KB    BYTES_KB
------------------------------ ------------------ ---------- ----------- ------------ ---------- ----------
SYS.LOB_TEST                   TABLE                 1         2147483645 2147483644    1024        64
SYS.SYS_IL0000073541C00002$$   LOBINDEX              1         2147483645 2147483644    1024        64
SYS.SYS_LOB0000073541C00002$$  LOBSEGMENT            230       2147483645 2147483415    1024        3143872

 

6) Truncate Will Reclaim the Space for Lob ( for both Basic file and Secure file )

SQL> truncate table lob_test; 

Table truncated.

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST'
) ;

TABLE_NAME            TOTAL_BLOCKS      USED_BLOCKS
--------------------------------------------------------------
LOB_TEST                    8            3

SQL>

Tablespace              Used MB     Free MB    Total MB    Pct. Free
---------------------- ----------- ----------- ----------- ----------
TTS_NAME             0         3,072       3,072         100               ---->> Reclaimed after truncate.

 

SQL> SELECT owner||'.'||SEGMENT_NAME NAME, SEGMENT_TYPE TYPE,
EXTENTS, MAX_EXTENTS, MAX_EXTENTS - EXTENTS LEFT_EXTENTS,
NEXT_EXTENT/1024 next_kb, bytes/1024 bytes_kb
FROM DBA_SEGMENTS
WHERE tablespace_name = 'TTS_NAME' ; 2 3 4 5

NAME TYPE EXTENTS MAX_EXTENTS LEFT_EXTENTS NEXT_KB BYTES_KB
------------------------------ ------------------ ---------- 
SYS.LOB_TEST TABLE 1 2147483645 2147483644 1024 64
SYS.SYS_IL0000073541C00002$$ LOBINDEX 1 2147483645 2147483644 1024 64
SYS.SYS_LOB0000073541C00002$$ LOBSEGMENT 1 2147483645 2147483644 1024 128

 

-- Tested in 11g Same Result::

 

 

[test]/tmp> sqlplus

SQL*Plus: Release 11.2.0.4.0 Production on Mon Jul 10 18:26:21 2017

Copyright (c) 1982, 2013, Oracle. All rights reserved.

SQL> CREATE SMALLFILE TABLESPACE "TTS_NAME" DATAFILE '/grdbms/64bit/app/oracle/oradata/xxx/DB01.dbf'
SIZE 3072M REUSE AUTOEXTEND ON NEXT 100M MAXSIZE 3072M
LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; 2 3

Tablespace created.

SQL> create table lob_test (id number, data blob) tablespace "TTS_NAME";

Table created.

SQL> create sequence lob_test_seq;

Sequence created.

SQL> Create directory TEST as '/tmp';

Directory created.

SQL> grant read,write on directory TEST to sys;

Grant succeeded.

SQL> Create Funcation as in 12c in above stesp

SQL> 

Tablespace             Used MB      Free MB    Total MB    Pct. Free
---------------------- ----------- ----------- ----------- ----------

TTS_NAME            0         3,072        3,072        100

 

SQL> DECLARE
src_file BFILE := bfilename('TEST', 'test.dat');
dst_file BLOB;
lgh_file BINARY_INTEGER;
cur_id NUMBER(10);
BEGIN
FOR i IN 1..500                                                                        ----->>> Insert 1 to 500
LOOP
INSERT INTO lob_test(id,data) VALUES(lob_test_seq.nextval,empty_blob())
RETURNING id into cur_id;
-- lock record
SELECT data INTO dst_file FROM lob_test WHERE id=cur_id FOR UPDATE;

dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
lgh_file := dbms_lob.getlength(src_file);
dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
dbms_lob.fileclose(src_file);
END LOOP;
END;
/

PL/SQL procedure successfully completed.

SQL> select sum(dbms_lob.getchunksize(data))/1024/1024 from lob_test;

SUM(DBMS_LOB.GETCHUNKSIZE(DATA))/1024/1024
------------------------------------------
3.87763977

SQL> SELECT owner||'.'||SEGMENT_NAME NAME, SEGMENT_TYPE TYPE,
EXTENTS, MAX_EXTENTS, MAX_EXTENTS - EXTENTS LEFT_EXTENTS,
NEXT_EXTENT/1024 next_kb, bytes/1024 bytes_kb
FROM DBA_SEGMENTS
WHERE tablespace_name = 'TTS_NAME' ; 2 3 4 5

NAME
--------------------------------------------------------------------------------
TYPE EXTENTS MAX_EXTENTS LEFT_EXTENTS NEXT_KB BYTES_KB
------------------ ---------- ----------- ------------ ---------- ----------
SYS.LOB_TEST
TABLE 2 2147483645 2147483643 1024 128

SYS.SYS_IL0000110586C00002$$
LOBINDEX 17 2147483645 2147483628 1024 2048

SYS.SYS_LOB0000110586C00002$$
LOBSEGMENT 219 2147483645 2147483426 1024 2359296

SQL> DECLARE
src_file BFILE := bfilename('TEST', 'test.dat');
dst_file BLOB;
lgh_file BINARY_INTEGER;
cur_id NUMBER(10);
BEGIN
FOR i IN 1..500
LOOP
INSERT INTO lob_test(id,data) VALUES(lob_test_seq.nextval,empty_blob())
RETURNING id into cur_id;
-- lock record
SELECT data INTO dst_file FROM lob_test WHERE id=cur_id FOR UPDATE;

dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
lgh_file := dbms_lob.getlength(src_file);
dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
dbms_lob.fileclose(src_file);
END LOOP;
END; 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20 /
DECLARE
*
ERROR at line 1:
ORA-01691: unable to extend lob segment SYS.SYS_LOB0000110586C00002$$ by 8192
in tablespace TTS_NAME
ORA-06512: at "SYS.DBMS_LOB", line 928
ORA-06512: at line 16

Tablespace Used MB Free MB Total MB Pct. Free
---------------------- ----------- ----------- ----------- ----------
SYSAUX 494 26 520 5
UNDOTBS1 51 59 110 54
USERS 18,325 949 19,274 5
SYSTEM 756 14 770 2
TTS_NAME 3,011 61 3,072 2

SQL> select sum(dbms_lob.getchunksize(data))/1024/1024 from lob_test;

SUM(DBMS_LOB.GETCHUNKSIZE(DATA))/1024/1024
------------------------------------------
3.87763977

 

SQL> select table_name,

trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST');

TABLE_NAME TOTAL_BLOCKS USED_BLOCKS
------------------------------ ------------ -----------
LOB_TEST             16                         16

SQL> delete from lob_test;

500 rows deleted.

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST');

TABLE_NAME               TOTAL_BLOCKS USED_BLOCKS
----------------------- ------------ -----------
LOB_TEST                     16           16

SQL> DECLARE
src_file BFILE := bfilename('TEST', 'test.dat');
dst_file BLOB;
lgh_file BINARY_INTEGER;
cur_id NUMBER(10);
BEGIN
FOR i IN 1..500
LOOP
INSERT INTO lob_test(id,data) VALUES(lob_test_seq.nextval,empty_blob())
RETURNING id into cur_id;
-- lock record
SELECT data INTO dst_file FROM lob_test WHERE id=cur_id FOR UPDATE;

dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
lgh_file := dbms_lob.getlength(src_file);
dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
dbms_lob.fileclose(src_file);
END LOOP;
END; 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20 /
DECLARE
*
ERROR at line 1:
ORA-01691: unable to extend lob segment SYS.SYS_LOB0000110586C00002$$ by 8192
in tablespace TTS_NAME
ORA-06512: at "SYS.DBMS_LOB", line 928
ORA-06512: at line 16

SQL> truncate table lob_test;

Table truncated.

SQL> select table_name,
trunc(gbi) total_blocks,
to_number(substr(gbi,instr(gbi,'.')+1)) used_blocks
from ( select table_name, get_block_info( table_name ) gbi, rownum
from user_tables where Table_name='LOB_TEST'); 2 3 4 5

TABLE_NAME           TOTAL_BLOCKS    USED_BLOCKS
----------------------------------- ------------ 
LOB_TEST                 8              3

 

 

NOTE:

We have many options to reclaim the space for LOB Segment . But we need to identify the Application code about the Command what they are using exactly. If Code uses Delete Command then DB level we cannot see any improvement for Block or Segment level free space.

So check what is the command used by Application code and confirm with this Steps.

 

Refer:

How to Shrink a Securefile LOB Using Online Redefinition (DBMS_REDEFINITION)? (Doc ID 1394613.1)
How To Reclaim Wasted Space on The Segment (Table, Index and LOB) and Tablespace Levels (Doc ID 1682748.1)
Why is no space released after an ALTER TABLE ... SHRINK? (Doc ID 820043.1)
Primary Note:Overview of Online Redefinition of Tables (DBMS_REDEFINITION) (Doc ID 1357825.1)

 

 

 

#########sample 2  

SEGMENT SHRINK and Details. (Doc ID 242090.1) To BottomTo Bottom

 

SEGMENT SHRINK

SEGMENT SHRINK and Details. (Doc ID 242090.1) To BottomTo Bottom

* ***

PURPOSE
========
In Oracle10g and onwards, we have the option to shrink a segment, which will help DBAs to manage the space in better way.
This feature also help for better performance for query.

SCOPE & APPLICATION
===================
Information on new Oracle10g feature.

Oracle 10g Segment shrink
=========================

Mandatory
=========
Init.ora parameter 'Compatible' must be >=10.0

Shrink operations can be performed only on segments in locally managed
tablespaces with automatic segment space management (ASSM).


How it works
============

1. Enable row movement for the table.
SQL> ALTER TABLE user_name.table_name ENABLE ROW MOVEMENT;

2. Shrink table but don't want to shrink HWM (High Water Mark).
SQL> ALTER TABLE user_name.table_name SHRINK SPACE COMPACT;

3. Shrink table and HWM too.
SQL> ALTER TABLE user_name.table_name SHRINK SPACE;

4. Shrink table and all dependent index too.
SQL> ALTER TABLE user_name.table_name SHRINK SPACE CASCADE;

5. Shrink table under MView.
SQL> ALTER TABLE <table name> SHRINK SPACE;

6. Shrink Index only.
SQL> ALTER INDEX <index nam> SHRINK SPACE;

7.. alter table TABLE_NAME disable ROW MOVEMENT;

 

 

Restrictions on the shrink_clause, 10gR1
========================================
1. You cannot specify this clause for a cluster, a clustered table, or any
object with a LONG column.
2. Segment shrink is not supported for LOB segments even if CASCADE is
specified.
3. Segment shrink is not supported for tables with function-based indexes.
4. This clause does not shrink mapping tables or overflow segments of
index-organized tables, even if you specify CASCADE.
5. You cannot shrink a table that is the primary table of an ON COMMIT
materialized view. Rowid materialized views must be rebuilt after the
shrink operation.
6. Table with a domain index is not supported.

Restrictions on the shrink_clause, 10gR2
========================================
1. You cannot specify this clause for a cluster, a clustered table, or any
object with a LONG column.
2. Segment shrink is not supported for tables with function-based indexes or
bitmap join indexes.
3. This clause does not shrink mapping tables of index-organized tables,
even if you specify CASCADE.
4. You cannot specify this clause for a compressed table.
5. You cannot shrink a table that is the primary table of an ON COMMIT
materialized view. Rowid materialized views must be rebuilt after the
shrink operation.
6. Table with a domain index is not supported.

Restrictions on the shrink_clause, 11gR1
========================================
1. You cannot combine this clause with any other clauses in the same ALTER TABLE
statement.
2. You cannot specify this clause for a cluster, a clustered table, or any
object with a LONG column.
3. Segment shrink is not supported for tables with function-based indexes or
bitmap join indexes.
4. This clause does not shrink mapping tables of index-organized tables, even if
you specify CASCADE.
5. You cannot specify this clause for a compressed table.
6. You cannot shrink a table that is the primary table of an ON COMMIT
materialized view. Rowid materialized views must be rebuilt after the shrink
operation.

Restrictions on the shrink_clause, 11gR2
========================================
1. You cannot combine this clause with any other clauses in the same ALTER TABLE statement.
2. You cannot specify this clause for a cluster, a clustered table, or any object with a LONG column.
3. Segment shrink is not supported for tables with function-based indexes, domain indexes, or bitmap join indexes.
4. This clause does not shrink mapping tables of index-organized tables, even if you specify CASCADE.
5. You cannot specify this clause for a compressed table.
6. You cannot shrink a table that is the primary table of an ON COMMIT materialized view. Rowid materialized views must be rebuilt after the shrink operation.

Restrictions on the shrink_clause, 12cR1
========================================
1. You cannot combine this clause with any other clauses in the same ALTER TABLE statement.
2. You cannot specify this clause for a cluster, a clustered table, or any object with a LONG column.
3. Segment shrink is not supported for tables with function-based indexes, domain indexes, or bitmap join indexes.
4. This clause does not shrink mapping tables of index-organized tables, even if you specify CASCADE.
5. You can specify this clause for a table with Advanced Row Compression enabled (ROW STORE COMPRESS ADVANCED). You cannot specify this clause for a table with any other type of table compression enabled.
6. You cannot shrink a table that is the primary table of an ON COMMIT materialized view. Rowid materialized views must be rebuilt after the shrink operation.

Restrictions on the shrink_clause, 12cR2
========================================
1. You cannot combine this clause with any other clauses in the same ALTER TABLE statement.
2. You cannot specify this clause for a cluster, a clustered table, or any object with a LONG column.
3. Segment shrink is not supported for tables with function-based indexes, domain indexes, or bitmap join indexes.
4. This clause does not shrink mapping tables of index-organized tables, even if you specify CASCADE.
5. You can specify this clause for a table with Advanced Row Compression enabled (ROW STORE COMPRESS ADVANCED). You cannot specify this clause for a table with any other type of table compression enabled.
6. You cannot shrink a table that is the primary table of an ON COMMIT materialized view. Rowid materialized views must be rebuilt after the shrink operation.

Query/DML Concurrency
=======================
The online phase of segment shrink is done with DML-compatible locks. Hence DMLs
can coexist during this phase. During the space-release/HWM adjustment phase,
incompatible locks will be acquired on the table, hence, DMLs will block on
shrink.

There are no user visible errors that shrink will cause on DMLs.

Queries cache the segment HWM. Oracle guarantees that the HWM always moves forward,
hence CR (consistent read) is not required on segment header and extent map blocks. The only operations
that cause the segment HWM to move backward are drop and truncate.

We allow queries to coexist with drop/truncate DDLs since queries do not acquire locks.
If after the drop/truncate, the space gets reused in some other segment, then the
queries get "8103 - object does not exist" external error message.

During segment shrink, the segment’s incarnation number is changed in the bitmap
blocks and segment header when the segment HWM is adjusted. Subsequent data block
changes happen at this newer incarnation number.

Queries that span this phase can die with an external error "10632 - invalid rowid"
if

1) They read the updated bitmap blocks (that have new inc#). Note that this failure
happens if the space is not reused

2) The space got reused for some other object or the same object.


Limitations on Online Segment Shrink, 10gR2:
============================================
Within an ASSM tablespace, all segment types are eligible for online segment shrink except these:

- IOT mapping tables
- Tables with rowid based materialized views
- Tables with function-based indexes


Dependency Maintenance and Restrictions on Shrink
=================================================
The only dependency that will be taken care of during segment shrink is the index.
The indexes will not be in an unusable state after shrink.

The compaction phase of segment shrink will be done as insert/delete pairs. The
DML triggers will not be fired during data movement phase. Since the data does
not change, it is not required to fire the triggers.

ROWID based triggers should be disabled before issuing a shrink since it will not
fire during shrink.

Segment shrink cannot be done on objects with on-commit materialized views.
Materialized views that are based on primary key need not be refreshed or rebuilt
after shrink.

However, it is the DBA’s responsibility to refresh/rebuild the materialized views
that are rowid based.

Availability
============
Segment shrink is done online, thereby it increases the availability of the object.
While conventional DML operations can coexist with segment shrink, parallel DMLs
cannot.

During segment shrink, data will be moved as part of the compaction phase. During
compaction locks will be held on individual rows and/or blocks containing the data.
This will cause the concurrent DMLs like updates and deletes to serialize on the
locks. The compaction will be done in units of smaller transactions, so the availability
of the object will not be impacted significantly.

However during certain phases of segment shrink (when the HWM is adjusted), the segment
will have to be locked in exclusive mode.

This phase is for a very short duration and should impact the availability of the
object less significantly.

Security
========
The privileges required to execute segment shrink on an object will be the same
as that for ALTER object.

Detail Example
===============

SQL> set serveroutput on
SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
12 v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 1
FS3 Blocks = 1
FS4 Blocks = 3
Full Blocks = 0

PL/SQL procedure successfully completed.

SQL> alter table t_shrink shrink space compact;
alter table t_shrink shrink space compact
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled

SQL> ALTER TABLE t_shrink ENABLE ROW MOVEMENT;
Table altered.

SQL> ALTER TABLE t_shrink SHRINK SPACE COMPACT;
Table altered.

SQL> set serveroutput on
SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
12 v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 0
FS3 Blocks = 0
FS4 Blocks = 2
Full Blocks = 1

PL/SQL procedure successfully completed.

SQL> ALTER TABLE t_shrink SHRINK SPACE;
Table altered.

SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
12 v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 0
FS3 Blocks = 0
FS4 Blocks = 1
Full Blocks = 1

PL/SQL procedure successfully completed.

SQL>

========

To monitor the progress of a long running SHRINK operation you may execute the pl/sql block in this note. You should see a change in the number of blocks. And it is not possible to verify how much time it still need to take for now.

For specific details on the output of the pl/sql blocks in this Note please reference the following documentation:

For 9i:
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96612/d_space2.htm#1002701

For 10gR2:
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_space.htm#sthref6026

For 11gR1:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28419/d_space.htm#sthref7301

For 11gR2:
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_space.htm#ARPLS68113

For 12cR1:
http://docs.oracle.com/database/121/ARPLS/d_space.htm#ARPLS68113

For 12cR2:
http://docs.oracle.com/database/122/ARPLS/DBMS_SPACE.htm#ARPLS68113

Can I cancel shrink operation? :
====================
Shrinking space of a large segment can take a lot of time, e.g. tens of hours, and can generate lots of redo.
Therefore, it is not advised to interrupt a shrink statement.

Best approach would be:

1. Initially, only use:
SQL> alter table shrink space compact;
This also takes long but should have little impact because of only short dml locks

2. Only when convenient, issue
SQL> alter table shrink space;

Before running in production, it is advised to test for possible impact in your test environment.


RELATED DOCUMENTS
-----------------
SQL Reference Manual, 10.1 and 10.2
Oracle® Database Administrator's Guide10g Release 1 and 2

Note:149516.1 BMB versus Freelist Segment: DBMS_SPACE.UNUSED_SPACE and DBA_TABLES.EMPTY_BLOCKS

 

 

 

##sample 3

Oracle Streams enables the sharing of data and events in a data stream, either within a database or from one database to another. This article is intended to provide information regarding the management of LOGMNR_RESTART_CKPT$ table.

SOLUTION

Periodically, the mining process checkpoints itself for quicker restart.
These checkpoint information is maintained in the SYSAUX tablespace by default.

From Oracle 10.2 onwards, the purging of logmnr_restart_ckpt$ is done automatically
by Oracle. There is a capture parameter checkpoint_retention_time that determines how
frequently the purge occurs.

CHECKPOINT_RETENTION_TIME, controls the amount of checkpoint data that is retained by
moving the FIRST_SCN of the capture process forward. When the checkpoint_retention_time
is exceeded (default = 60 days), the FIRST_SCN is moved and the Streams metadata tables
previous to this scn(FIRST_SCN) can be purged. Space in the SYSAUX tablespace should be
reclaimed at this time.

You can alter checkpoint_retention_time to lesser value to purge the metatdata
tables more frequently using the following syntax :

exec dbms_capture_adm.alter_capture(capture_name =>'<name> ',CHECKPOINT_RETENTION_TIME=><days>);

For example :-

exec dbms_capture_adm.alter_capture(capture_name =>'STRMADMIN_CAPTURE ',CHECKPOINT_RETENTION_TIME=>7);



Here we are setting the retention time to 7 days. Any data in table logmnr_restart_ckpt$
older than 7 days is purged automatically.

You can then use the shrink command to manually free unused space both above and
below the high water mark of the table.

alter table system.LOGMNR_RESTART_CKPT$ enable row movement;
alter table system.LOGMNR_RESTART_CKPT$ shrink space ;
alter table system.LOGMNR_RESTART_CKPT$ modify lob (CKPT_INFO) (shrink space);
alter table system.LOGMNR_RESTART_CKPT$ disable row movement;


The index associated with the table can be shrunk using

alter index <index name> shrink space;
 
 
 
 
 
##########sample  3 實際操作
 

一、查詢刪除前表空間
select A.tablespace_name,total,free,(total-free),round((total-free)/total,4)*100
from (select tablespace_name,sum(bytes) free from dba_free_space group by tablespace_name) A,
(select tablespace_name,sum(bytes) total from dba_data_files group by tablespace_name) B where
A.tablespace_name = B.tablespace_name and A.tablespace_name = 'IGFS_DATA';


SELECT a.tablespace_name ,b.maxbytes/1024/1024/1024 "maxbyes_GB",total/1024/1024/1024 "bytes_GB",free/1024/1024/1024 "free_GB",(total-free) /1024/1024/1024 "use_GB",
ROUND((total-free)/total,4)*100 "use_%",ROUND((total-free)/b.maxbytes,4)*100 "maxuse_%"
FROM
(SELECT tablespace_name,SUM(bytes) free FROM DBA_FREE_SPACE
GROUP BY tablespace_name
) a,
(SELECT tablespace_name,sum(case autoextensible when 'YES' then maxbytes else bytes end) maxbytes,SUM(bytes) total FROM DBA_DATA_FILES
GROUP BY tablespace_name
) b
WHERE a.tablespace_name=b.tablespace_name
order by "maxuse_%" desc;


二、刪除表數據 delete 時候只花了7-8分鍾不到的時間.。
delete from user.ab_LOG where trade_date>='20140101' and trade_date<='20141231' ;
Commit;
delete from user.ab_LOG where trade_date>='20150101' and trade_date<='20151231' ;
Commit;
三、整理表空間
開啟行移動
ALTER TABLE user.ab_LOG ENABLE ROW MOVEMENT;
收縮表(會阻塞DML操作並回收對應的索引),shrink space 一共花了2個小時多一點。釋放了總共30G 數據空間。
ALTER TABLE user.ab_LOG SHRINK SPACE CASCADE;
關閉行移動
ALTER table user.ab_LOG disable ROW MOVEMENT;


->開始時間 :21:55
TABLESPACE_NAME maxbyes_GB bytes_GB free_GB use_GB use_% maxuse_%
------------------------------ ---------- ---------- ---------- ---------- ---------- ----------
tabspace 297.999863 302.820267 13.5998535 289.220413 95.51 97.05

->觀察時間:22:42
TABLESPACE_NAME maxbyes_GB bytes_GB free_GB use_GB use_% maxuse_%
------------------------------ ---------- ---------- ---------- ---------- ---------- ----------
tabspace 297.999863 302.820267 13.7063599 289.113907 95.47 97.02


->結束時間23:49

TABLESPACE_NAME maxbyes_GB bytes_GB free_GB use_GB use_% maxuse_%
------------------------------ ---------- ---------- ---------- ---------- ---------- ----------
tabspace 297.999863 302.820267 40.4465332 262.373734 86.64 88.04


##實際操作的過程如下,發現有如下問題。

問題1,敲下shrink space 時候,其他都是黑盒操作,也不知道完成進度。嘗試使用如下sql 觀察,發現該sql 只能觀察dml, 不能觀察ddl, 也就是shrink space
這種ddl 觀察不到記錄。

#########方法1 觀察sql , 無效
SELECT A.USERNAME,
A.SID,
A.SERIAL#,
A.OPNAME,
A.TARGET,
A.START_TIME,
A.LAST_UPDATE_TIME,
C.OSUSER,
C.MACHINE,
C.PROGRAM,
ROUND(A.SOFAR * 100 / TOTALWORK, 0) || '%' AS JINDU,
A.TIME_REMAINING,
A.ELAPSED_SECONDS,
B.SQL_TEXT
FROM GV$SESSION_LONGOPS A, GV$SQL B, GV$SESSION C
WHERE A.SQL_ADDRESS = B.ADDRESS
AND A.SQL_HASH_VALUE = B.HASH_VALUE
AND A.SID = C.SID
AND C.STATUS = 'ACTIVE'
####

##方法2 有效
咨詢測試人員,當時的恢復環境,同樣的數據做數據清理,花了多久時間。得到的答復是1個半小時。實際上生產環境消耗的時間超過1個半小時,
經過分析,如果想評估shrink space 的時間,時間主要消耗臨時表空間征用,估計跟重建索引有關系。
可以觀察redo 產生的日志量,如果測試產生的日志量 達到了50G, 那么生產環境也應該消耗了50G 左右

##經過分析,測試環境的單個redo在2G 左右,生產單個redo 在200M 左右,所以生產redo 切換太頻繁,也可能導致生產實際運行時間超過測試環境。
redo size
測試2G
生產200M;
清理60萬shrinks space AB_LOG 時間,造成了時間消耗從測試環境只要 1個半小時變到 生產環境 2個小時.
######


問題2:
由於linux 空間超時時間為300秒,echo $TMOUT

如果直接在前台sqlplus 執行 SHRINK SPACE
可以會超時退出,這個時候,觀察后台sql 仍然在跑,理論上不影響該條sql 執行。但是后繼這種情況可以考慮如下2種
方法。


方法1: oracle 用戶下, 未經驗證
執行直接 TMOUT=0


方法2 ,在pl/sql devoloper 端執行
這個時候。應該沒有超時限制

 

 

 

 

############ 查看lob 對應的segment name

select owner,table_name,column_name,segment_name,index_name from dba_lobs;

 
#####


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM