tep 1: Mapping Old Tablespaces to New Tablespaces
To handle your consolidation (40 old tablespaces to 8 new ones, with groupings like 5 old to 1 new), we'll start by creating a mapping table if you don't have one already. This is similar to the ts_config from the optimized approach but tailored to your needs. It ensures all old tablespaces are accounted for, with a fallback to a default new tablespace (e.g., 'NEW_DATA8') for any unmapped ones.
Create and Populate Mapping Table
Run this on your source database to set up the mappings. Customize the INSERT statements with your actual 40 old tablespaces and their groupings to the 8 new ones. The example below uses your sample (assuming PLO_DATA_01, PLO_DATA_02, ILO_DATA_01, ILA_INDEX_02, PLA_DATA_01 all map to TRU_DATA_01 as a group).
-- Create mapping table (if not exists)
CREATE TABLE ts_mappings (
old_tablespace VARCHAR2(30) NOT NULL,
new_tablespace VARCHAR2(30) NOT NULL,
mapping_group NUMBER, -- Optional: Group ID for 5-to-1 style consolidations
notes VARCHAR2(200), -- Description or reason
CONSTRAINT pk_ts_mappings PRIMARY KEY (old_tablespace)
);
-- Populate with your mappings (example for one group; repeat for all 40 old -> 8 new)
-- Group 1: 5 old to TRU_DATA_01
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes) VALUES ('PLO_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes) VALUES ('PLO_DATA_02', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes) VALUES ('ILO_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes) VALUES ('ILA_INDEX_02', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes) VALUES ('PLA_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
-- Add more groups (e.g., for other 35 old tablespaces mapping to remaining 7 new ones)
-- INSERT INTO ts_mappings ... for Group 2 to 8
-- Auto-populate any missing old tablespaces from dba_tablespaces with fallback
MERGE INTO ts_mappings tm
USING (SELECT tablespace_name FROM dba_tablespaces WHERE tablespace_name NOT IN (SELECT old_tablespace FROM ts_mappings)) src
ON (tm.old_tablespace = src.tablespace_name)
WHEN NOT MATCHED THEN
INSERT (old_tablespace, new_tablespace, mapping_group, notes)
VALUES (src.tablespace_name, 'NEW_DATA8', 8, 'Fallback for unmapped tablespaces');
COMMIT;Script to List Old to New Mappings
This query outputs the mappings in a grouped format, similar to your example (old tablespaces listed under their new one). It uses hierarchical formatting for readability.
-- Query to display mappings (grouped by new_tablespace)
SELECT
new_tablespace || ' (Group ' || mapping_group || '):' AS new_group,
LISTAGG(old_tablespace, ', ') WITHIN GROUP (ORDER BY old_tablespace) AS old_tablespaces
FROM ts_mappings
GROUP BY new_tablespace, mapping_group
ORDER BY mapping_group;
-- Alternative flat output (like your example)
SELECT old_tablespace || '. ' || new_tablespace AS mapping
FROM ts_mappings
ORDER BY new_tablespace, old_tablespace;Example Output (Based on Your Sample):
PLO_DATA_01. TRU_DATA_01
PLO_DATA_02. TRU_DATA_01
ILO_DATA_01. TRU_DATA_01
ILA_INDEX_02. TRU_DATA_01
PLA_DATA_01. TRU_DATA_01Validation Check: Run this to ensure no old tablespaces are missed:
SELECT tablespace_name AS missing_old_ts
FROM dba_tablespaces
MINUS
SELECT old_tablespace FROM ts_mappings;Step 2: Script to List Users/Tables/Indexes Using Old Tablespaces and Suggested New Mappings
This is a comprehensive, robust script that queries DBA views to find:
- Users with default tablespaces set to old ones, and suggested new defaults.
- Tables in old tablespaces, with suggested new tablespaces.
- Indexes in old tablespaces, with suggested new tablespaces.
It handles multi-schema environments, includes counts for summary, and generates ALTER statements for remapping (e.g., for post-import execution). Run this on the source database.
-- Comprehensive query for users, tables, and indexes with old -> new mappings
WITH mappings AS (
SELECT old_tablespace, new_tablespace
FROM ts_mappings
)
-- Users with default old tablespaces
SELECT 'USER' AS object_type,
du.username AS object_name,
du.default_tablespace AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace,
'ALTER USER "' || du.username || '" DEFAULT TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') ||
' QUOTA UNLIMITED ON ' || NVL(m.new_tablespace, 'NEW_DATA8') || ';' AS alter_script
FROM dba_users du
LEFT JOIN mappings m ON m.old_tablespace = du.default_tablespace
WHERE du.default_tablespace IN (SELECT old_tablespace FROM mappings)
UNION ALL
-- Tables in old tablespaces
SELECT 'TABLE' AS object_type,
dt.owner || '.' || dt.table_name AS object_name,
dt.tablespace_name AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace,
'ALTER TABLE "' || dt.owner || '"."' || dt.table_name || '" MOVE TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') || ';' AS alter_script
FROM dba_tables dt
LEFT JOIN mappings m ON m.old_tablespace = dt.tablespace_name
WHERE dt.tablespace_name IN (SELECT old_tablespace FROM mappings)
UNION ALL
-- Indexes in old tablespaces
SELECT 'INDEX' AS object_type,
di.owner || '.' || di.index_name AS object_name,
di.tablespace_name AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace,
'ALTER INDEX "' || di.owner || '"."' || di.index_name || '" REBUILD TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') ||
' PARALLEL 4;' AS alter_script -- Parallel for performance
FROM dba_indexes di
LEFT JOIN mappings m ON m.old_tablespace = di.tablespace_name
WHERE di.tablespace_name IN (SELECT old_tablespace FROM mappings)
ORDER BY object_type, old_tablespace, object_name;
-- Summary counts
SELECT object_type,
old_tablespace,
COUNT(*) AS count,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace
FROM (
SELECT 'USER' AS object_type, default_tablespace AS old_tablespace FROM dba_users WHERE default_tablespace IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'TABLE', tablespace_name FROM dba_tables WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'INDEX', tablespace_name FROM dba_indexes WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
) sub
LEFT JOIN ts_mappings m ON m.old_tablespace = sub.old_tablespace
GROUP BY object_type, old_tablespace, NVL(m.new_tablespace, 'NEW_DATA8')
ORDER BY object_type, old_tablespace;Key Features:
- Robustness: Uses LEFT JOIN with NVL for fallbacks; handles cases where old tablespace isn't explicitly mapped.
- Output Includes ALTER Scripts: Ready-to-run statements for manual remapping if needed (e.g., if not using Data Pump).
- Filtering: Add WHERE du.username IN ('SCHEMA1', 'SCHEMA2') or similar to focus on specific schemas.
- Other Places Default Tablespace is Used: Users' default tablespaces affect new object creation (e.g., tables without specified tablespace). The script captures this. Also check temporary tablespaces (du.temporary_tablespace), but they're not remapped by default—add if needed.
Validation for LOBs/Partitions (Bonus): These often reference tablespaces indirectly.
-- LOBs using old tablespaces
SELECT owner || '.' || table_name || '.' || column_name AS lob_object,
tablespace_name AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new
FROM dba_lobs
LEFT JOIN ts_mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings);
-- Partitions using old tablespaces
SELECT table_owner || '.' || table_name || '.' || partition_name AS partition_object,
tablespace_name AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new
FROM dba_tab_partitions
LEFT JOIN ts_mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings);Step 3: Does Data Pump (Export/Import) with REMAP_TABLESPACE Handle User Defaults, Tables, Indexes, etc.?
No, not completely—here's a clear explanation and script to handle it.
- What REMAP_TABLESPACE Handles:
- It automatically remaps the tablespace for schema objects like tables, indexes, LOBs, and partitions during import. For example, if a table is in old_tablespace 'PLO_DATA_01', it will be placed in 'TRU_DATA_01' if you specify REMAP_TABLESPACE=PLO_DATA_01:TRU_DATA_01.
- This works for metadata-only exports (CONTENT=METADATA_ONLY) or full exports.
- It does not remap:
- Users' default tablespaces (e.g., where new objects go if no tablespace is specified).
- Quotas on tablespaces.
- Temporary tablespaces or other user attributes.
- For consolidations (multiple old to one new), you need multiple REMAP_TABLESPACE clauses (e.g., REMAP_TABLESPACE=PLO_DATA_01:TRU_DATA_01,REMAP_TABLESPACE=PLO_DATA_02:TRU_DATA_01,...).
- Limitations and Manual Steps:
- After import, run ALTER USER statements on the target to update defaults and quotas.
- Indexes may need rebuilding if invalid post-import.
- Test with a small export/import to verify.
Script to Generate REMAP_TABLESPACE Clause for Data Pump
Run this on source to get the clause for impdp:
SELECT LISTAGG('REMAP_TABLESPACE=' || old_tablespace || ':' || new_tablespace, ',') WITHIN GROUP (ORDER BY old_tablespace) AS remap_clause
FROM ts_mappings;Example Data Pump Commands
- Export metadata only: expdp system/password@source_db DIRECTORY=DATA_PUMP_DIR DUMPFILE=metadata.dmp LOGFILE=export.log FULL=Y CONTENT=METADATA_ONLY
- Import with remap: impdp system/password@target_db DIRECTORY=DATA_PUMP_DIR DUMPFILE=metadata.dmp LOGFILE=import.log [paste remap_clause from above]
Post-Import Script for Users (Run on Target)
Use the ALTER USER statements from Step 2's output. Also:
-- Validate post-import
SELECT username, default_tablespace FROM dba_users WHERE default_tablespace IN (SELECT old_tablespace FROM ts_mappings@source_dblink); -- Use dblink if comparing source/targetIf you provide your full list of 40 old tablespaces and their exact mappings to 8 new ones (or patterns), I can pre-populate the INSERTs or refine further. Also specify schemas or Oracle version for tweaks!
Since you're using the Oracle Data Pump API (e.g., DBMS_DATAPUMP) in an RDS environment for your tablespace consolidation (40 old tablespaces to 8 new ones), and expdp/impdp commands are not viable, I'll tailor the solution to leverage the Data Pump API while addressing your need to identify where default tablespaces are used (users, tables, indexes, and other objects) and confirm how REMAP_TABLESPACE handles these during migration. I'll also ensure the scripts are robust, RDS-compatible, and cover all places where default tablespaces are relevant.
Key Considerations for RDS and Data Pump API
- RDS Constraints: In Oracle RDS, expdp/impdp require specific configurations (e.g., S3 integration via rdsadmin.rdsadmin_s3_tasks). The Data Pump API (DBMS_DATAPUMP) is supported but must use an RDS DATA_PUMP_DIR or S3 bucket. You need the RDS master user or a user with DATAPUMP_EXP_FULL_DATABASE/DATAPUMP_IMP_FULL_DATABASE roles.
- Default Tablespaces: As previously discussed, default tablespaces are set at the user level (default_tablespace, temporary_tablespace), database level (DEFAULT_PERMANENT_TABLESPACE, DEFAULT_TEMP_TABLESPACE), and quotas (dba_ts_quotas). Other objects (tables, indexes, LOBs, etc.) have assigned tablespaces, which are remapped via DBMS_DATAPUMP.METADATA_REMAP.
- REMAP_TABLESPACE with Data Pump API: The API supports remapping tablespaces for objects (tables, indexes, LOBs, partitions) but does not update user default tablespaces or quotas. These require separate ALTERstatements.
- Your Ask:
- Identify all places where default tablespaces are used (users, database, quotas, and objects like tables/indexes).
- Provide scripts to list old-to-new tablespace mappings for users/tables/indexes.
- Confirm how Data Pump API with REMAP_TABLESPACE handles these during migration.
Below, I'll provide:
- A script to list all places default tablespaces are used, with old-to-new mappings.
- A script to identify users/tables/indexes in old tablespaces and their suggested new mappings.
- A Data Pump API script for migration, including REMAP_TABLESPACE, with post-migration steps for user defaults/quotas.
Step 1: Identify Where Default Tablespaces Are Used
Default tablespaces are relevant in several places. Since your target RDS is empty, we'll query the source database to capture these and generate setup scripts for the target. This assumes you have a ts_mappings table (as previously discussed) with mappings like PLO_DATA_01 -> TRU_DATA_01, etc., covering your 40 old to 8 new tablespaces.
-- Create ts_mappings if not exists (run on source)
CREATE TABLE ts_mappings (
old_tablespace VARCHAR2(30) NOT NULL,
new_tablespace VARCHAR2(30) NOT NULL,
mapping_group NUMBER, -- For 5-to-1 consolidation tracking
notes VARCHAR2(200),
CONSTRAINT pk_ts_mappings PRIMARY KEY (old_tablespace)
);
-- Populate with your mappings (example; customize for all 40)
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes)
VALUES ('PLO_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes)
VALUES ('PLO_DATA_02', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes)
VALUES ('ILO_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes)
VALUES ('ILA_INDEX_02', 'TRU_DATA_01', 1, 'Group 1 consolidation');
INSERT INTO ts_mappings (old_tablespace, new_tablespace, mapping_group, notes)
VALUES ('PLA_DATA_01', 'TRU_DATA_01', 1, 'Group 1 consolidation');
-- Add remaining 35 old tablespaces, mapping to TRU_DATA_02 to TRU_DATA_08
-- Auto-populate unmapped tablespaces with fallback
MERGE INTO ts_mappings tm
USING (SELECT tablespace_name FROM dba_tablespaces WHERE tablespace_name NOT IN (SELECT old_tablespace FROM ts_mappings)) src
ON (tm.old_tablespace = src.tablespace_name)
WHEN NOT MATCHED THEN
INSERT (old_tablespace, new_tablespace, mapping_group, notes)
VALUES (src.tablespace_name, 'NEW_DATA8', 8, 'Fallback for unmapped tablespaces');
COMMIT;-- before it is run. This table defines the mapping from old to new tablespace names.
-- Example of creating and populating ts_mappings:
-- CREATE GLOBAL TEMPORARY TABLE ts_mappings (
-- old_tablespace VARCHAR2(30),
-- new_tablespace VARCHAR2(30)
-- ) ON COMMIT PRESERVE ROWS;
--
-- INSERT INTO ts_mappings (old_tablespace, new_tablespace) VALUES ('USERS', 'NEW_DATA8');
-- INSERT INTO ts_mappings (old_tablespace, new_tablespace) VALUES ('TEMP', 'NEW_TEMP8');
-- COMMIT;
-- Part 1: List all tablespace usages that are in the ts_mappings table
-- This section helps you verify what will be changed.
WITH mappings AS (
SELECT old_tablespace, new_tablespace FROM ts_mappings
)
SELECT 'DATABASE_DEFAULT_PERMANENT' AS context,
property_value AS old_tablespace_or_object,
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = property_value), 'NEW_DATA8') AS suggested_new_tablespace
FROM database_properties
WHERE property_name = 'DEFAULT_PERMANENT_TABLESPACE'
AND property_value IN (SELECT old_tablespace FROM mappings)
UNION ALL
SELECT 'DATABASE_DEFAULT_TEMPORARY',
property_value,
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = property_value), 'NEW_TEMP8')
FROM database_properties
WHERE property_name = 'DEFAULT_TEMP_TABLESPACE'
AND property_value IN (SELECT old_tablespace FROM mappings)
UNION ALL
SELECT 'USER_DEFAULT',
username,
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = default_tablespace), 'NEW_DATA8')
FROM dba_users
WHERE default_tablespace IN (SELECT old_tablespace FROM mappings)
UNION ALL
SELECT 'USER_TEMPORARY',
username,
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = temporary_tablespace), 'NEW_TEMP8')
FROM dba_users
WHERE temporary_tablespace IN (SELECT old_tablespace FROM mappings)
UNION ALL
SELECT 'USER_QUOTA',
username || ': ' || tablespace_name || ' (Quota: ' ||
CASE WHEN max_bytes = -1 THEN 'UNLIMITED' ELSE TO_CHAR(max_bytes / 1024 / 1024) || 'M' END || ')',
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = tablespace_name), 'NEW_DATA8')
FROM dba_ts_quotas
WHERE tablespace_name IN (SELECT old_tablespace FROM mappings)
UNION ALL
-- New section for Materialized Views
SELECT 'MATERIALIZED_VIEW',
owner || '.' || mview_name,
NVL((SELECT new_tablespace FROM mappings WHERE old_tablespace = dba_segments.tablespace_name), 'NEW_DATA8')
FROM dba_mviews
JOIN dba_segments ON dba_mviews.owner = dba_segments.owner AND dba_mviews.mview_name = dba_segments.segment_name
WHERE dba_segments.tablespace_name IN (SELECT old_tablespace FROM mappings)
AND dba_segments.segment_type = 'MATERIALIZED VIEW'
ORDER BY context, old_tablespace_or_object;
-- Part 2: Generate setup scripts for the target environment (e.g., RDS)
-- You can copy and paste the output of this section to run the ALTER statements.
SELECT 'ALTER DATABASE DEFAULT TABLESPACE ' ||
NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace =
(SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_PERMANENT_TABLESPACE')), 'NEW_DATA8') || ';'
FROM dual
WHERE (SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_PERMANENT_TABLESPACE') IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'ALTER DATABASE DEFAULT TEMPORARY TABLESPACE ' ||
NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace =
(SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_TEMP_TABLESPACE')), 'NEW_TEMP8') || ';'
FROM dual
WHERE (SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_TEMP_TABLESPACE') IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'ALTER USER "' || username || '" DEFAULT TABLESPACE ' ||
NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace = default_tablespace), 'NEW_DATA8') || ';'
FROM dba_users
WHERE default_tablespace IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'ALTER USER "' || username || '" TEMPORARY TABLESPACE ' ||
NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace = temporary_tablespace), 'NEW_TEMP8') || ';'
FROM dba_users
WHERE temporary_tablespace IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'ALTER USER "' || username || '" QUOTA ' ||
CASE WHEN max_bytes = -1 THEN 'UNLIMITED' ELSE TO_CHAR(max_bytes / 1024 / 1024) || 'M' END ||
' ON ' || NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace = tablespace_name), 'NEW_DATA8') || ';'
FROM dba_ts_quotas
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
-- New section for Materialized Views
SELECT 'ALTER MATERIALIZED VIEW "' || owner || '"."' || mview_name || '" MOVE TABLESPACE ' ||
NVL((SELECT new_tablespace FROM ts_mappings WHERE old_tablespace = dba_segments.tablespace_name), 'NEW_DATA8') || ';'
FROM dba_mviews
JOIN dba_segments ON dba_mviews.owner = dba_segments.owner AND dba_mviews.mview_name = dba_segments.segment_name
WHERE dba_segments.tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
AND dba_segments.segment_type = 'MATERIALIZED VIEW';
Output Includes:
- Database-level default permanent and temporary tablespaces.
- User-level default and temporary tablespaces.
- User quotas on old tablespaces.
- Suggested new mappings with fallback (NEW_DATA8/NEW_TEMP8).
Notes:
- Adjust NEW_TEMP8 if your temporary tablespaces have a different naming convention (e.g., TRU_TEMP_01).
- Save the output ALTER statements to run on the target after creating the new tablespaces.
Step 2: List Users/Tables/Indexes Using Old Tablespaces and New Mappings
This script identifies all users, tables, indexes, and other objects (LOBs, partitions, materialized views) in old tablespaces and maps them to new ones. It also generates ALTER statements for manual adjustments if needed (though REMAP_TABLESPACE handles most objects).
WITH mappings AS (
SELECT old_tablespace, new_tablespace FROM ts_mappings
)
SELECT 'USER' AS object_type,
username AS object_name,
default_tablespace AS old_tablespace,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace,
'ALTER USER "' || username || '" DEFAULT TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') || ';' AS alter_script
FROM dba_users
LEFT JOIN mappings m ON m.old_tablespace = default_tablespace
WHERE default_tablespace IN (SELECT old_tablespace FROM mappings)
UNION ALL
SELECT 'TABLE',
owner || '.' || table_name,
tablespace_name,
NVL(m.new_tablespace, 'NEW_DATA8'),
'ALTER TABLE "' || owner || '"."' || table_name || '" MOVE TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') || ';'
FROM dba_tables
LEFT JOIN mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'INDEX',
owner || '.' || index_name,
tablespace_name,
NVL(m.new_tablespace, 'NEW_DATA8'),
'ALTER INDEX "' || owner || '"."' || index_name || '" REBUILD TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') || ' PARALLEL 4;'
FROM dba_indexes
LEFT JOIN mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'LOB',
owner || '.' || table_name || '.' || column_name,
tablespace_name,
NVL(m.new_tablespace, 'NEW_DATA8'),
'LOBs are remapped automatically by Data Pump'
FROM dba_lobs
LEFT JOIN mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'PARTITION',
table_owner || '.' || table_name || '.' || partition_name,
tablespace_name,
NVL(m.new_tablespace, 'NEW_DATA8'),
'Partitions are remapped automatically by Data Pump'
FROM dba_tab_partitions
LEFT JOIN mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'MVIEW',
owner || '.' || mview_name,
tablespace_name,
NVL(m.new_tablespace, 'NEW_DATA8'),
'ALTER MATERIALIZED VIEW "' || owner || '"."' || mview_name || '" MOVE TABLESPACE ' || NVL(m.new_tablespace, 'NEW_DATA8') || ';'
FROM dba_mviews
LEFT JOIN mappings m ON m.old_tablespace = tablespace_name
WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
ORDER BY object_type, old_tablespace, object_name;
-- Summary counts
SELECT object_type,
old_tablespace,
COUNT(*) AS count,
NVL(m.new_tablespace, 'NEW_DATA8') AS suggested_new_tablespace
FROM (
SELECT 'USER' AS object_type, default_tablespace AS old_tablespace FROM dba_users WHERE default_tablespace IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'TABLE', tablespace_name FROM dba_tables WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'INDEX', tablespace_name FROM dba_indexes WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'LOB', tablespace_name FROM dba_lobs WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'PARTITION', tablespace_name FROM dba_tab_partitions WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
UNION ALL
SELECT 'MVIEW', tablespace_name FROM dba_mviews WHERE tablespace_name IN (SELECT old_tablespace FROM ts_mappings)
) sub
LEFT JOIN ts_mappings m ON m.old_tablespace = sub.old_tablespace
GROUP BY object_type, old_tablespace, NVL(m.new_tablespace, 'NEW_DATA8')
ORDER BY object_type, old_tablespace;Output Includes:
- Users, tables, indexes, LOBs, partitions, and materialized views in old tablespaces.
- Suggested new tablespaces based on ts_mappings.
- ALTER scripts for manual moves (though Data Pump handles tables/indexes/LOBs/partitions via REMAP_TABLESPACE).
Step 3: Data Pump API Migration with REMAP_TABLESPACE
The Data Pump API (DBMS_DATAPUMP) will handle remapping tablespaces for schema objects (tables, indexes, LOBs, partitions, materialized views) but not user defaults or quotas. Below is a PL/SQL script for export and import, tailored for RDS with S3 integration, followed by post-migration steps for user defaults.
Export Script (Run on Source)
This exports the full database or specific schemas to an S3 bucket via DATA_PUMP_DIR.
DECLARE
hdl NUMBER; -- Data Pump job handle
job_state VARCHAR2(30);
log_file VARCHAR2(100) := 'export.log';
dump_file VARCHAR2(100) := 'full_export_%U.dmp';
BEGIN
-- Open export job
hdl := DBMS_DATAPUMP.OPEN(
operation => 'EXPORT',
job_mode => 'FULL', -- or 'SCHEMA' for specific schemas
remote_link => NULL,
job_name => 'FULL_EXPORT_' || TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')
);
-- Specify dump file and log file in DATA_PUMP_DIR
DBMS_DATAPUMP.ADD_FILE(
handle => hdl,
filename => dump_file,
directory => 'DATA_PUMP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE
);
DBMS_DATAPUMP.ADD_FILE(
handle => hdl,
filename => log_file,
directory => 'DATA_PUMP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE
);
-- Enable compression for efficiency
DBMS_DATAPUMP.SET_PARAMETER(handle => hdl, name => 'COMPRESSION', value => 'ALL');
-- Parallelism for performance (adjust based on RDS instance)
DBMS_DATAPUMP.SET_PARALLEL(handle => hdl, degree => 4);
-- Start the job
DBMS_DATAPUMP.START_JOB(handle => hdl);
-- Monitor job status
job_state := 'UNDEFINED';
WHILE (job_state != 'COMPLETED' AND job_state != 'STOPPED') LOOP
DBMS_DATAPUMP.GET_STATUS(
handle => hdl,
mask => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR + DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS,
job_state => job_state
);
DBMS_LOCK.SLEEP(10); -- Wait 10 seconds
END LOOP;
-- Detach when done
DBMS_DATAPUMP.DETACH(handle => hdl);
EXCEPTION
WHEN OTHERS THEN
DBMS_DATAPUMP.DETACH(handle => hdl);
RAISE;
END;
/
-- Upload dump files to S3 (run as RDS master user)
BEGIN
rdsadmin.rdsadmin_s3_tasks.upload_to_s3(
p_bucket_name => 'your-rds-s3-bucket',
p_prefix => 'dmp_files/',
p_directory_name => 'DATA_PUMP_DIR'
);
END;
/Import Script (Run on Target RDS)
This imports the data, applying REMAP_TABLESPACE for objects. Run after creating the 8 new bigfile tablespaces (e.g., CREATE BIGFILE TABLESPACE TRU_DATA_01 DATAFILE SIZE 100M AUTOEXTEND ON NEXT 1G MAXSIZE UNLIMITED;).
DECLARE
hdl NUMBER;
job_state VARCHAR2(30);
log_file VARCHAR2(100) := 'import.log';
dump_file VARCHAR2(100) := 'full_export_%U.dmp';
BEGIN
-- Download dump files from S3
rdsadmin.rdsadmin_s3_tasks.download_from_s3(
p_bucket_name => 'your-rds-s3-bucket',
p_s3_prefix => 'dmp_files/',
p_directory_name => 'DATA_PUMP_DIR'
);
-- Open import job
hdl := DBMS_DATAPUMP.OPEN(
operation => 'IMPORT',
job_mode => 'FULL', -- or 'SCHEMA'
remote_link => NULL,
job_name => 'FULL_IMPORT_' || TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')
);
-- Specify dump file and log file
DBMS_DATAPUMP.ADD_FILE(
handle => hdl,
filename => dump_file,
directory => 'DATA_PUMP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE
);
DBMS_DATAPUMP.ADD_FILE(
handle => hdl,
filename => log_file,
directory => 'DATA_PUMP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE
);
-- Apply REMAP_TABLESPACE for all mappings
FOR rec IN (SELECT old_tablespace, new_tablespace FROM ts_mappings) LOOP
DBMS_DATAPUMP.METADATA_REMAP(
handle => hdl,
name => 'REMAP_TABLESPACE',
old_value => rec.old_tablespace,
value => rec.new_tablespace
);
END LOOP;
-- Transform LOBs to SecureFile (RDS best practice)
DBMS_DATAPUMP.METADATA_TRANSFORM(
handle => hdl,
name => 'LOB_STORAGE',
value => 'SECUREFILE'
);
-- Parallelism
DBMS_DATAPUMP.SET_PARALLEL(handle => hdl, degree => 4);
-- Start the job
DBMS_DATAPUMP.START_JOB(handle => hdl);
-- Monitor job status
job_state := 'UNDEFINED';
WHILE (job_state != 'COMPLETED' AND job_state != 'STOPPED') LOOP
DBMS_DATAPUMP.GET_STATUS(
handle => hdl,
mask => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR + DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS,
job_state => job_state
);
DBMS_LOCK.SLEEP(10);
END LOOP;
DBMS_DATAPUMP.DETACH(handle => hdl);
EXCEPTION
WHEN OTHERS THEN
DBMS_DATAPUMP.DETACH(handle => hdl);
RAISE;
END;
/Post-Import: Update User Defaults and Quotas
REMAP_TABLESPACE remaps tables, indexes, LOBs, partitions, and materialized views but not user defaults or quotas. Run the ALTER statements from Step 1's output on the target:
-- Example (from Step 1 output; customize based on your mappings)
ALTER DATABASE DEFAULT TABLESPACE TRU_DATA_01;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TRU_TEMP_01;
ALTER USER "SCHEMA1" DEFAULT TABLESPACE TRU_DATA_01;
ALTER USER "SCHEMA1" TEMPORARY TABLESPACE TRU_TEMP_01;
ALTER USER "SCHEMA1" QUOTA UNLIMITED ON TRU_DATA_01;
-- Repeat for all users/quotasPost-Import Validation
-- Validate object placement
SELECT object_type,
tablespace_name AS new_tablespace,
COUNT(*) AS count
FROM dba_objects
WHERE tablespace_name IN (SELECT new_tablespace FROM ts_mappings@source_dblink) -- Use dblink if needed
GROUP BY object_type, tablespace_name
ORDER BY object_type, tablespace_name;
-- Check for invalid objects
SELECT object_type, owner, object_name
FROM dba_objects
WHERE status = 'INVALID';
-- Verify user defaults
SELECT username, default_tablespace, temporary_tablespace
FROM dba_users
WHERE default_tablespace IN (SELECT new_tablespace FROM ts_mappings@source_dblink);
-- Gather statistics
EXEC DBMS_STATS.GATHER_DATABASE_STATS(cascade => TRUE, degree => 4);How Data Pump API with REMAP_TABLESPACE Handles Your Ask
- What It Handles:
- Tables, Indexes, LOBs, Partitions, Materialized Views: DBMS_DATAPUMP.METADATA_REMAPwith REMAP_TABLESPACE automatically moves these to the new tablespaces (e.g., PLO_DATA_01 -> TRU_DATA_01).
- Metadata-Only Export: If you export metadata only (CONTENT => 'METADATA'), it still remaps tablespace assignments for these objects.
- What It Doesn't Handle:
- User Default Tablespaces: default_tablespace and temporary_tablespace in dba_users remain unchanged; use ALTER USER.
- Quotas: Quotas on old tablespaces aren't carried over; reapply with ALTER USER ... QUOTA.
- Database Defaults: DEFAULT_PERMANENT_TABLESPACE and DEFAULT_TEMP_TABLESPACEneed ALTER DATABASE.
- RDS Notes: Ensure the target tablespaces exist before import. Use rdsadmin.rdsadmin_s3_tasks for dump file transfers. SecureFile LOBs are enforced for RDS compatibility.
Recommendations
- Before Migration:
- Create the 8 new bigfile tablespaces on the target RDS.
- Run Step 1 scripts on source to capture all default tablespace usages.
- Save the ALTER statements for target setup.
- During Migration: Use the Data Pump API scripts above, ensuring S3 bucket access and sufficient RDS storage.
- After Migration: Run the ALTER statements and validation queries.
- If You Share:
- Your full list of 40 old tablespaces and their mappings to 8 new ones.
- Specific schemas or Oracle version (e.g., 19c).
- Whether temporary tablespaces are consolidated separately. I can generate precise INSERTs for ts_mappings or adjust scripts.
No comments:
Post a Comment