标签:
Oracle Database - Enterprise Edition - Version 9.2.0.1 and later
Information in this document applies to any platform.
Checked for relevance on 17 April 2012
This note will discuss resizing of Oracle datafiles (larger or smaller)
The intended audience for this document is for experienced DBA‘s
Oracle file sizing is vital part of managing Oracle databases
In older versions (Oracle 7.1 and lower) the only methods available to resize tablespace storage were
* Drop and recreate the tablespace with different sized datafiles (decrease / shrink)
* Add one or more datafiles to the tablespace (increase)
Beginning in Oracle 7.2 Oracle introduced the ALTER DATABASE DATAFILE .... RESIZE command.
This option allows you to change the physical size of a datafile from what was specified during its creation.
To increase the size of a datafile, you would use the command:
where the size specified is larger than the existing file size.
The current size of a datafile may be found by querying V$DATAFILE.BYTES or DBA_DATA_FILES.BYTES
Examples:
In this example the size before resize was 1048576 bytes and after the resize 10567680 bytes
In this example the file was created with a size of 100K (CREATE_BYTES) and is currently 2 MB in size ... this shows that the file was resized.
To decrease the size of a datafile, you would use the command:
where the size specified is smaller than the existing file size.
The current size of a datafile may be found by querying V$DATAFILE.BYTES or DBA_DATA_FILES.BYTES (see section 1 for examples)
Reducing the size of a datafile is more complicated than increasing the size of a datafile as space cannot be deallocated from a datafile that is currently being used by database objects.
To remove space from a datafile, you have to have contiguous free space at the END of the datafile.
The view DBA_FREE_SPACE is used to display the free space (space not being used) in a datafile.
For example:
There are two large extents at the high end of the datafile
This means there are 1986560 unused bytes at the end of our datafile, almost 2 MB.
We want to leave some room for growth in our datafile, and depending on how the objects in that datafile allocate new extents, we could remove up to 1.89 MB of disk space from the datafile without damaging any objects in the tablespace.
If you have a large extent in the middle of a datafile, and some object taking up room at the end of the datafile, you can use the query FINDEXT.SQL below to find this object. If you export this object, then drop it, you should then free up contiguous space at the end of your datafile so you will be able to resize it smaller.
Make sure you leave enough room in the datafile for importing the object back into the tablespace.
A) For safety reasons, you should take a backup of your database whenever you change its structure, which includes altering the size of datafiles.
B) If you try to resize a datafile to a size smaller than is needed to contain all the database objects in that datafile, the following error is returned:
ORA-03297: file contains blocks of data beyond requested RESIZE value
Or
ORA-03297: file contains used data beyond requested RESIZE value
The resize operation will fail at this point.
C) If you try to resize a datafile larger than can be created, you will also get an error.
For instance, if trying to create a file of 2 GB, without having 2 GB of available disk space the following errors will be returned:
ORA-01237: cannot extend datafile
ORA-01110: data file : ‘‘
ORA-19502: write error on file "", blockno (blocksize=)
ORA-27072: File I/O error
If you check V$DATAFILE, you will see that the file size does not change unless the operation is successful.
D) MANUAL versus AUTOMATIC extension:
Be careful giving datafiles the AUTOEXTEND attribute, and make sure to specify the NEXT and MAXSIZE parameters.
If using dictionary managed tablespaces (DMT)
If using multiple database writers (db_writers > 1) in RDBMS versions below version 7.3.4.1, might be encounterd. This appears as ORA-7374 errors when accessing the datafile after it has been resized. The workaround is to shutdown and restart the database after resizing a datafile (a convenient time to take a backup). This will cause the new datafile size information to be refreshed to all the DBWR slave processes.
E) Please be aware that beside the command ‘ALTER DATABASE DATAFILE ... RESIZE ... ‘ there are still alternatives like the export and import utility (including DataPump) to perform a resize of a datafile. Using export/import will lead also result in a reorganization of the objects in the tablespace related to the datafile.
FINDEXT.SQL
Sample Output:
SHRINK_DATAFILE.SQL
Sample Output:
sqlplus / as sysdba
-- Setup for the testcase
alter system set recyclebin=on;
create tablespace test datafile ‘/u01/app/oracle/oradata/v10205/test.dbf‘ size 100m extent management local uniform size 1m;
select bytes from v$datafile where file# = 5;
!ls -alt /u01/app/oracle/oradata/v10205/test.dbf
create user test identified by test;
grant dba to test;
alter user test default tablespace test;
connect test/test;
-- Fill up the TEST Tablespace
BEGIN
for i in 1..19 LOOP
execute immediate ‘create table ‘ || ‘TEST‘||i ||‘ as select * from dba_objects‘;
end loop;
end;
/
select bytes-ebytes from (select sum(bytes) ebytes from dba_extents where file_id=5), dba_data_files where file_id=5;
select sum(bytes) from dba_free_space where file_id=5;
-- Examine the extent storage for the TEST datafile with FINDEXT.SQL
@FINDEXT
Segment Extent Summary
FILE_NAME FILE_ID
-------------------------------------------------- ----------
/u01/app/oracle/oradata/v10205/system01.dbf 1
/u01/app/oracle/oradata/v10205/undotbs01.dbf 2
/u01/app/oracle/oradata/v10205/sysaux01.dbf 3
/u01/app/oracle/oradata/v10205/users01.dbf 4
/u01/app/oracle/oradata/v10205/test.dbf 5
Enter value for file_id: 5
old 3: where file_id = &file_id
new 3: where file_id = 5
Segment Extent Summary
Owner Segment Name Type Extent# File# Block# Blocks
-------- ------------------------------ -------- ------- ----- ------ --------
TEST TEST1 TABLE 0 5 9 128
TEST TEST1 TABLE 1 5 137 128
TEST TEST1 TABLE 2 5 265 128
TEST TEST1 TABLE 3 5 393 128
TEST TEST1 TABLE 4 5 521 128
TEST TEST2 TABLE 0 5 649 128
...
TEST TEST18 TABLE 3 5 11273 128
TEST TEST18 TABLE 4 5 11401 128
TEST TEST19 TABLE 0 5 11529 128
TEST TEST19 TABLE 1 5 11657 128
TEST TEST19 TABLE 2 5 11785 128
TEST TEST19 TABLE 3 5 11913 128
TEST TEST19 TABLE 4 5 12041 128
-- DROP TABLES TEST2 TO TEST17 AND TEST19
BEGIN
for i in 2..17 LOOP
execute immediate ‘DROP table ‘ || ‘TEST‘||i;
end loop;
execute immediate ‘DROP TABLE TEST19‘;
end;
/
-- Examine the storage for the TEST datafile with FINDEXT.SQL
@FINDEXT
Segment Extent Summary
FILE_NAME FILE_ID
-------------------------------------------------- ----------
/u01/app/oracle/oradata/v10205/system01.dbf 1
/u01/app/oracle/oradata/v10205/undotbs01.dbf 2
/u01/app/oracle/oradata/v10205/sysaux01.dbf 3
/u01/app/oracle/oradata/v10205/users01.dbf 4
/u01/app/oracle/oradata/v10205/test.dbf 5
Enter value for file_id: 5
old 3: where file_id = &file_id
new 3: where file_id = 5
Segment Extent Summary
Owner Segment Name Type Extent# File# Block# Blocks
-------- ------------------------------ -------- ------- ----- ------ --------
TEST TEST1 TABLE 0 5 9 128
TEST TEST1 TABLE 1 5 137 128
TEST TEST1 TABLE 2 5 265 128
TEST TEST1 TABLE 3 5 393 128
TEST TEST1 TABLE 4 5 521 128
TEST TEST18 TABLE 0 5 10889 128
TEST TEST18 TABLE 1 5 11017 128
TEST TEST18 TABLE 2 5 11145 128
TEST TEST18 TABLE 3 5 11273 128
TEST TEST18 TABLE 4 5 11401 128
-- NOTE THAT THERE IS NOW A LARGE HOLE IN THE MIDDLE OF THE TEST TABLESPACE DATAFILE
-- Examine the Recylebin Contents for the Test Tablespace
SELECT ORIGINAL_NAME FROM DBA_RECYCLEBIN WHERE TS_NAME = ‘TEST‘;
-- Determine the the amount of data remaining in active extents in the TEST tablespace datafile
SELECT SUM(BYTES) FROM DBA_EXTENTS WHERE FILE_ID = 5;
SUM(BYTES)
----------
10485760
-- Remember .. when resizing datafiles smaller .. extra space should be allowed for future growth as well as space for the datafile headers
-- this test was run with an overhead of 10 (8K) blocks
-- Determine what objects must be moved in order for the resize to succeed
@SHRINK_DATAFILE.SQL
-- Show that the resize will not succeed with the objects in their present position
ALTER DATABASE DATAFILE ‘/u01/app/oracle/oradata/v10205/test.dbf‘ RESIZE 10567680;
ALTER DATABASE DATAFILE ‘/u01/app/oracle/oradata/v10205/test.dbf‘ RESIZE 10567680
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
-- Move the TEST18 table to another tablespace so that the resize can succeed
ALTER TABLE TEST18 MOVE TABLESPACE USERS;
-- Attempt to resize the table again
ALTER DATABASE DATAFILE ‘/u01/app/oracle/oradata/v10205/test.dbf‘ RESIZE 10567680;
ALTER DATABASE DATAFILE ‘/u01/app/oracle/oradata/v10205/test.dbf‘ RESIZE 10567680
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
-- The reason that this resize failed is there are still objects in the recycle bin ... they need to removed before the resize can succeed
purge tablespace test;
-- Tablespace purged.
-- Attempt the resize again
ALTER DATABASE DATAFILE ‘/u01/app/oracle/oradata/v10205/test.dbf‘ RESIZE 10567680;
-- Database altered.
select bytes from v$datafile where file# = 5;
!ls -alt /u01/app/oracle/oradata/v10205/test.dbf
-- Return the TEST18 table to the TEST tablespace
ALTER TABLE TEST18 MOVE TABLESPACE TEST;
-- CLEAN UP
CONNECT / AS SYSDBA
drop user test cascade;
drop tablespace test including contents and datafiles cascade constraints;
How to Resize a Datafile (文档 ID 1029252.6)
标签:
原文地址:http://www.cnblogs.com/future2012lg/p/4288242.html