Oracle多租户容器数据库(Multitenant Container Database)是Oracle 12c引入的重大架构革新。我在金融行业数据库迁移项目中首次接触这个架构时,发现它彻底改变了传统Oracle实例与数据库的一对一关系。核心设计是将多个可插拔数据库(PDB)整合到一个容器数据库(CDB)中,就像在服务器虚拟化中多个虚拟机共享同一台物理主机。
CDB作为管理容器,包含以下关键组件:
重要提示:在19c版本中,Oracle已明确将多租户架构作为未来发展方向,传统非CDB架构将被逐步淘汰。
使用DBCA图形化工具创建时,需特别注意勾选"Create as Container Database"选项。命令行方式更灵活:
sql复制CREATE DATABASE CDB1
ENABLE PLUGGABLE DATABASE
SEED FILE_NAME_CONVERT=('/opt/oracle/oradata/CDB1/','/opt/oracle/oradata/CDB1/pdbseed/')
SYSTEM DATAFILES SIZE 1G AUTOEXTEND ON
DEFAULT TEMPORARY TABLESPACE temp TEMPFILE SIZE 500M
UNDO TABLESPACE undotbs1 DATAFILE SIZE 1G;
创建PDB的三种典型方式:
sql复制CREATE PLUGGABLE DATABASE SALESPDB
ADMIN USER salesadm IDENTIFIED BY "ComplexPwd123"
FILE_NAME_CONVERT=('/opt/oracle/oradata/CDB1/pdbseed/',
'/opt/oracle/oradata/CDB1/salespdb/');
sql复制CREATE PLUGGABLE DATABASE TESTPDB FROM SALESPDB
FILE_NAME_CONVERT=('/opt/oracle/oradata/CDB1/salespdb/',
'/opt/oracle/oradata/CDB1/testpdb/')
SERVICE_NAME_CONVERT=('sales_service','test_service');
sql复制-- 在原库执行
BEGIN
DBMS_PDB.DESCRIBE(
pdb_descr_file => '/tmp/olddb.xml');
END;
/
-- 在CDB中执行
CREATE PLUGGABLE DATABASE OLDPDB
USING '/tmp/olddb.xml'
NOCOPY
TEMPFILE REUSE;
在多租户环境中,资源争用是最常见的问题。通过CDB级别的资源计划可以防止单个PDB耗尽系统资源:
sql复制BEGIN
DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN(
plan => 'DAYTIME_PLAN',
comment => '日间资源分配方案');
DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE(
plan => 'DAYTIME_PLAN',
pluggable_database => 'SALESPDB',
shares => 3,
utilization_limit => 80,
parallel_server_limit => 50);
END;
/
虽然PDB共享CDB的表空间,但可以通过以下方式实现存储隔离:
sql复制ALTER PLUGGABLE DATABASE SALESPDB
SET DEFAULT TABLESPACE sales_data
DATAFILE '/u01/oradata/CDB1/salespdb/sales01.dbf' SIZE 10G;
sql复制ADMINISTER KEY MANAGEMENT CREATE KEYSTORE '/u01/wallet' IDENTIFIED BY "WalletPwd123";
ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY "WalletPwd123";
ADMINISTER KEY MANAGEMENT SET KEY IDENTIFIED BY "WalletPwd123" WITH BACKUP;
bash复制# 整库备份(包含所有PDB)
rman target sys/Password123@CDB1
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
# 单PDB备份
RMAN> BACKUP PLUGGABLE DATABASE SALESPDB, HRPDB
FORMAT '/backup/%U_%d_%T.bkp';
当某个PDB发生逻辑错误时,可以单独执行时间点恢复而不影响其他PDB:
sql复制RMAN> RUN {
SET UNTIL TIME "TO_DATE('2023-07-20 14:00:00','YYYY-MM-DD HH24:MI:SS')";
RESTORE PLUGGABLE DATABASE SALESPDB;
RECOVER PLUGGABLE DATABASE SALESPDB;
ALTER PLUGGABLE DATABASE SALESPDB OPEN RESETLOGS;
}
sql复制-- 查看各PDB资源使用情况
SELECT con_id, name, open_mode,
round(cpu_used/1000,2) "CPU(s)",
round(memory_used/1024/1024) "Memory(MB)"
FROM v$containers;
sql复制-- 切换容器上下文
ALTER SESSION SET CONTAINER = SALESPDB;
-- 生成AWR报告
@?/rdbms/admin/awrrpt.sql
sql复制-- 创建公共用户
CREATE USER C##DBA_ADMIN IDENTIFIED BY "AdminPwd456"
CONTAINER=ALL;
GRANT CREATE SESSION, CDB_DBA TO C##DBA_ADMIN
CONTAINER=ALL;
-- 创建PDB本地用户
ALTER SESSION SET CONTAINER = SALESPDB;
CREATE USER SALES_USER IDENTIFIED BY "UserPwd789";
sql复制-- CDB级别审计
AUDIT CREATE SESSION BY C##DBA_ADMIN WHENEVER SUCCESSFUL;
-- PDB级别审计
ALTER SESSION SET CONTAINER = SALESPDB;
AUDIT SELECT TABLE, INSERT TABLE BY SALES_USER;
错误现象:
code复制ORA-65005: missing or invalid file pattern for file...
解决方案:
sql复制-- 检查数据文件状态
SELECT name, status FROM v$datafile WHERE con_id = (SELECT con_id FROM v$pdbs WHERE name = 'SALESPDB');
-- 重命名文件路径
ALTER PLUGGABLE DATABASE SALESPDB OPEN;
ALTER SESSION SET CONTAINER = SALESPDB;
ALTER DATABASE MOVE DATAFILE '/old_path/sales01.dbf' TO '/new_path/sales01.dbf';
当发现某个PDB响应变慢时:
sql复制-- 查看资源使用排行
SELECT r.con_id, p.name,
r.cpu_consumed_time, r.io_requests
FROM v$rsrcpdbmetric r, v$pdbs p
WHERE r.con_id = p.con_id
ORDER BY r.cpu_consumed_time DESC;
使用DBMS_PDB包是最可靠的方式,但需要注意:
多租户环境推荐采用以下升级路径:
@?/rdbms/admin/utlrp.sql重新编译无效对象sql复制-- 卸载PDB
ALTER PLUGGABLE DATABASE SALESPDB CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE SALESPDB UNPLUG INTO '/tmp/salespdb.xml';
-- 在新CDB中注册
CREATE PLUGGABLE DATABASE SALESPDB
USING '/tmp/salespdb.xml'
NOCOPY
TEMPFILE REUSE;
在金融行业的生产环境中,我们通常会采用Golden Gate实现零停机迁移。通过配置抽取进程从源库捕获变更,同时在目标PDB初始化数据后启动复制进程,待数据同步后切换应用连接。