Definição
O que é Multitenant?
Multitenant Architecture (introduzida no Oracle 12c) permite consolidar múltiplos bancos de dados em um único Container Database (CDB). Cada banco é uma Pluggable Database (PDB) completamente isolada mas compartilhando processos de background e memória (SGA).
CDB (Container Database)
O banco "pai" que gerencia os recursos globais. Contém:
CDB$ROOT: Container raiz com dicionário de dados do CDB
PDB$SEED: Template para criar novos PDBs
PDBs: Bancos plugáveis (até 4.096 por CDB no 21c)
PDB (Pluggable Database)
Banco auto-contido com seus próprios objetos, usuários e esquemas. Comporta-se como banco tradicional mas compartilha infraestrutura do CDB. Pode ser plugged/unplugged facilmente entre CDBs.
Benefícios
- Redução de overhead: 1 SGA/PGA para N bancos
- Patching/Upgrade centralizado (apenas CDB)
- Clonagem rápida de PDBs (minutos vs horas)
- Portabilidade: plug/unplug entre servidores
- Consolidação: reduz hardware e custos de licenciamento
Comparação: Non-CDB vs CDB
| Aspecto | Non-CDB (Tradicional) | CDB/PDB (Multitenant) |
|---|---|---|
| Instâncias | 1 por banco | 1 para múltiplos bancos |
| Memória | SGA duplicada por banco | SGA compartilhada |
| Patching | Cada banco separadamente | Uma vez no CDB |
| Backup | Por banco | CDB completo ou PDB individual |
| Clonagem | Lento (horas) | Rápido (minutos) |
Aplicação Prática
Criando um CDB
# Usando DBCA em silent mode para criar CDB
dbca -silent \
-createDatabase \
-templateName General_Purpose.dbc \
-gdbName ORCL \
-sid ORCL \
-createAsContainerDatabase true \
-numberOfPDBs 1 \
-pdbName PDB1 \
-pdbAdminPassword Welcome1 \
-sysPassword Welcome1 \
-systemPassword Welcome1 \
-storageType FS \
-datafileDestination /u01/app/oracle/oradata \
-characterSet AL32UTF8
Gerenciando PDBs
-- Conectar ao CDB
CONNECT sys/Welcome1@orcl AS SYSDBA
-- Ver todos os containers
SELECT CON_ID, NAME, OPEN_MODE FROM V$CONTAINERS;
-- Criar novo PDB a partir do SEED
CREATE PLUGGABLE DATABASE pdb2
ADMIN USER pdb2admin IDENTIFIED BY Welcome1
FILE_NAME_CONVERT = ('/pdbseed/', '/pdb2/');
-- Abrir PDB
ALTER PLUGGABLE DATABASE pdb2 OPEN;
-- Salvar estado (abrir automaticamente no startup)
ALTER PLUGGABLE DATABASE pdb2 SAVE STATE;
-- Trocar de container (session switch)
ALTER SESSION SET CONTAINER = pdb2;
-- Fechar PDB
ALTER PLUGGABLE DATABASE pdb2 CLOSE IMMEDIATE;
-- Excluir PDB
DROP PLUGGABLE DATABASE pdb2 INCLUDING DATAFILES;
Clonagem de PDB
-- Clonar PDB local (mesmo CDB)
-- PDB origem deve estar em READ ONLY
ALTER PLUGGABLE DATABASE pdb1 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE pdb1 OPEN READ ONLY;
CREATE PLUGGABLE DATABASE pdb1_clone
FROM pdb1
FILE_NAME_CONVERT = ('/pdb1/', '/pdb1_clone/');
ALTER PLUGGABLE DATABASE pdb1 CLOSE;
ALTER PLUGGABLE DATABASE pdb1 OPEN;
ALTER PLUGGABLE DATABASE pdb1_clone OPEN;
-- Clonar PDB via database link (de outro CDB)
CREATE PLUGGABLE DATABASE pdb_remote_clone
FROM pdb1@remote_cdb
FILE_NAME_CONVERT = ('/remote/', '/local/');
-- Snapshot cloning (instantâneo com storage CoW)
CREATE PLUGGABLE DATABASE pdb_snap
FROM pdb1 SNAPSHOT COPY;
Plug/Unplug PDB
-- Unplug PDB (gera XML manifest)
ALTER PLUGGABLE DATABASE pdb1 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE pdb1 UNPLUG INTO '/tmp/pdb1.xml';
DROP PLUGGABLE DATABASE pdb1 KEEP DATAFILES;
-- Verificar compatibilidade antes de plug
SET SERVEROUTPUT ON
DECLARE
compatible BOOLEAN := FALSE;
BEGIN
compatible := DBMS_PDB.CHECK_PLUG_COMPATIBILITY(
pdb_descr_file => '/tmp/pdb1.xml'
);
IF compatible THEN
DBMS_OUTPUT.PUT_LINE('PDB is compatible');
ELSE
DBMS_OUTPUT.PUT_LINE('PDB is NOT compatible');
END IF;
END;
/
-- Plug PDB em novo CDB
CREATE PLUGGABLE DATABASE pdb1
USING '/tmp/pdb1.xml'
NOCOPY
TEMPFILE REUSE;
ALTER PLUGGABLE DATABASE pdb1 OPEN;
-- Executar script de correção se necessário
ALTER SESSION SET CONTAINER = pdb1;
@?/rdbms/admin/noncdb_to_pdb.sql
Usuários Common vs Local
-- Common User (existe em todos os PDBs, prefixo C##)
-- Criar no CDB$ROOT
ALTER SESSION SET CONTAINER = CDB$ROOT;
CREATE USER c##admin IDENTIFIED BY Welcome1 CONTAINER=ALL;
GRANT DBA TO c##admin CONTAINER=ALL;
-- Local User (existe apenas em PDB específico)
ALTER SESSION SET CONTAINER = pdb1;
CREATE USER app_user IDENTIFIED BY Welcome1;
GRANT CONNECT, RESOURCE TO app_user;
-- Ver usuários
SELECT USERNAME, COMMON, CON_ID
FROM CDB_USERS
WHERE USERNAME IN ('C##ADMIN', 'APP_USER');
-- Resource Manager para PDBs (limitar CPU/IO por PDB)
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA;
-- Criar plano CDB
DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN(
plan => 'cdb_plan',
comment => 'CDB Resource Plan'
);
-- Diretivas (shares de recursos)
DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE(
plan => 'cdb_plan',
pluggable_database => 'pdb1',
shares => 3,
utilization_limit => 80 -- max 80% CPU
);
DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA;
DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA;
END;
/
-- Ativar plano
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'cdb_plan';
Resultado Esperado
Criar e Gerenciar CDB/PDB
Criar, abrir, fechar e excluir PDBs
Clonar PDBs
Snapshot e remote cloning
Plug/Unplug
Migrar PDBs entre CDBs
Gerenciar Usuários
Common vs Local users
Resource Manager
Limitar recursos por PDB
Troubleshooting
Resolver problemas de compatibilidade