4

Arquitetura Multitenant (CDB/PDB)

Container Database, Pluggable Databases, gestão e benefícios

📖

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

Anterior Próximo