Oracle 19c原题解析:多租户、监听与SQL优化实战

发布时间:2026/9/19 14:10:50
Oracle 19c原题解析:多租户、监听与SQL优化实战 简介备考 Oracle 19c 认证或维护企业级数据库环境的读者可以用这份原题资料强化多租户架构知识。资源收录了带正确答案的考试原题内容以多租户为核心涉及应用 PDB 在应用根和应用种子之间的创建与同步顺序、PDB 在不同 CDB 间近乎零停机迁移时需要的归档模式与本地回滚模式条件、PDB 快照可完整或稀疏复制的语义区别以及 RMAN 备份连接 CDB$ROOT 与 PDB 的权限范围、AWR 快照在 STATISTICS_LEVEL 不同取值下的生成时机等高频考点。其中应用 PDB 的同步顺序与迁移条件尤其容易混淆值得反复推敲。题目贴近实际管理场景适合系统学习后作针对性训练也可作为考前快速回顾的清单。整包为 1 份 PDF 文档容量约 350KB轻便易打开目前已有 327 人浏览学习适合需要强化 Oracle 19c 多租户架构、PDB 生命周期管理和备份监控概念的从业者。1. 别只刷原题Oracle 19c资料PDF第二部分到底在考什么拿到“Oracle 19c原题资料PDF第二部分”的人第一反应通常是找题目、背答案。但翻过目录就会发现这一部分的题眼并不在“答案”里而在数据库日常维护中最容易翻车的地方多租户架构、监听配置、SQL执行计划和备份恢复。PDF里的题目只是把生产环境里的坑重新摆了一遍真正要练的是“为什么这样选”和“出问题时看哪里”。这篇博文就顺着第二部分最常见的考点把Oracle 19c需要动手验证的技术点拆开讲每个点都给出可复现的命令和参数说明。适合正在准备OCP 19c认证的DBA也适合刚接手19c生产环境的运维工程师——比单纯背题更有用。2. 看懂Oracle 19c的版本与架构题CDB、PDB和实例配置2.1 多租户架构的必答点CDB与PDB的关系Oracle 12c之后引入了多租户架构19c已经默认以CDB方式安装。原题第二部分常出现这类题一个CDB里能有多少个PDBPDB和实例是什么关系答案其实都落在“共享还是隔离”这个点上。CDBContainer Database是容器库它包含Root容器CDB$ROOT、种子PDBPDB$SEED以及业务PDB。实例instance是基于内存和后台进程的运行实体一个CDB实例可以同时打开多个PDB但一个PDB同一时刻只能由这一个实例服务——这是与旧版非CDB架构最大的差别。连接方式也变了以前是sqlplus user/passdbname现在需要明确指定服务名。服务名默认就是PDB名比如连接PDB时写sqlplus sys/Oracle123localhost:1521/pdb1 as sysdba而不是用全局数据库名。很多原题会让考生判断“在CDB里创建用户”还是“在PDB里创建用户”正确答案是业务用户必须建在PDB里CDB$ROOT里只放DBA账户和Oracle内部账户。这一点在19c考试里几乎必考。2.2 用DBCA命令行快速建一个19c单机CDB图形界面DBCA能做的事命令行全都能做。原题第二部分会要求写出静默安装的过程因为生产环境多半没有图形界面。下面是一个最小化创建单机CDB外加一个PDB的命令dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbname ORCL19C \ -sid ORCL19C \ -createAsContainerDatabase true \ -numberOfPDBs 1 \ -pdbName PDB1 \ -pdbAdminName pdbadmin \ -pdbAdminPassword Oracle123 \ -sysPassword Oracle123 \ -systemPassword Oracle123 \ -storageType FS \ -datafileDestination /u01/app/oracle/oradata \ -characterSet AL32UTF8 \ -memoryMgmtType AUTO_SGA \ -totalMemory 2048注意几个参数-createAsContainerDatabase true是开启多租户-numberOfPDBs 1和-pdbName PDB1决定创建几个PDB。如果只想建CDB不要PDB把numberOfPDBs设为0。-pdbAdminPassword是PDB的本地管理员密码注意这个账号只在PDB里生效不能用来登录CDB。-storageType FS表示使用文件系统存储如果配置了ASM盘组这里改成ASM并加上-diskGroupName DATA。执行完后用lsnrctl status检查监听是否注册了CDB和PDB的服务名。2.3 版本号的坑19.25.0.0.241015 和 Release Update原题里常出现版本相关题目比如“Oracle 19c最新版本号是什么”“如何查看当前补丁级别”。这里有一个高频混淆点Oracle 19c的基础版本号恒为19.0.0.0.0更新版本RU通过补丁升级所以实际看到的版本号形如19.25.0.0.241015。这个数字含义依次是19主版本、25更新序号、0、0最后是补丁发布日期2410152024年10月15日。查询当前真实版本用一条SQLSELECT version, version_full, release_update FROM v$instance;输出示例VERSION VERSION_FULL RELEASE_UPDATE 19.0.0.0.0 19.25.0.0.241015 25v$instance里的version永远是19.0.0.0.0真正区分补丁级别的是version_full和release_update。release_update是当前应用的最新RU序号如果查询结果为null说明这是基础版还没打补丁。生产环境升级后第一件事就是确认这一步否则后续配置容易踩到行为不一致的坑。提示19c的补丁分为Release Update每季度和Release Update Revision在RU基础上修的版本选择哪个取决于你的维护窗口和需求不是越新越好。3. 原题高发区监听和连接管理的三个必调参数3.1 listener.ora与tnsnames.ora的配置对照原题第二部分有一类题专门考“监听无法启动”或“服务器端和客户端命名解析的区别”。讲白了监听是数据库进程它负责接收入站连接请求然后转发给对应实例。listener.ora是监听进程自己的配置tnsnames.ora是客户端或本地工具用来解析连接串的两个文件位置不同作用也不同别搞混。一个最小可用的listener.ora如下LISTENER (DESCRIPTION_LIST (DESCRIPTION (ADDRESS (PROTOCOL TCP)(HOST db-server1)(PORT 1521)) (ADDRESS (PROTOCOL IPC)(KEY EXTPROC1521)) ) ) SID_LIST_LISTENER (SID_LIST (SID_DESC (GLOBAL_DBNAME ORCL19C.world) (SID_NAME ORCL19C) ) )这里的SID_LIST是静态注册用的。19c默认使用动态注册即实例启动时通过local_listener参数去找监听进程把服务名注册上去。如果你的环境里动态注册失败才需要静态清单。动态注册的关键是local_listener和remote_listener两个参数ALTER SYSTEM SET local_listener(ADDRESS(PROTOCOLTCP)(HOSTdb-server1)(PORT1521)) SCOPEBOTH; ALTER SYSTEM REGISTER;ALTER SYSTEM REGISTER是手动触发注册不用重启实例。检查监听里是否已有服务名用lsnrctl services3.2 监听启动失败的排查命令“oracle监听服务无法启动”是搜索热词也是原题里的常见故障。遇到这种情况先别急着重启按这个顺序查# 1. 检查监听进程是否还在 ps -ef | grep tnslsnr # 2. 启动监听带详细日志 lsnrctl start # 3. 如果启动失败直接看监听日志尾行 tail -50 $ORACLE_BASE/diag/tnslsnr/$(hostname)/listener/alert/log.xml最常见的原因是端口占用或listener.ora里的HOST写成了具体IP但服务器IP变了。所以启动后立刻执行lsnrctl status查看返回的Listener参数确认HOST和PORT是否和实际网卡一致。如果看到The listener supports no services不是监听挂了而是实例没有成功注册。这时回到实例里执行ALTER SYSTEM REGISTER然后再次lsnrctl services。3.3 从SQL*Plus到DBeaver驱动与连接串原题还会考各种客户端连接方式特别是Windows下用PL/SQL Developer或DBeaver连Oracle 19c。这里有一个高频坑Oracle 19c的JDBC驱动版本必须匹配至少用ojdbc8。连接到PDB时服务名不是数据库名而是PDB名。下面是DBeaver里配置连接时要填的内容连接项填写值说明Hostdb-server1数据库服务器IP或主机名Port1521默认监听端口Service namePDB1注意是服务名不是SIDUsernamepdbadminPDB的本地用户PasswordOracle123和创建PDB时设置的一致JDBC Driverojdbc819c必须要8.1以上版本如果JDBC报ORA-28040: No matching authentication protocol说明客户端driver版本太老升级ojdbc8就能解决。如果你要在Maven项目里连Oracle 19c依赖坐标这样写dependency groupIdcom.oracle.database.jdbc/groupId artifactIdojdbc8/artifactId version19.25.0.0/version /dependency版本号里的19.25.0.0和数据库的补丁号对应别只写ojdbc8的通用版本否则容易遇到协议不匹配。4. 原题案例SQL优化和存储过程的答题套路4.1 执行计划里的全表扫描怎么破原题第二部分给得最多的就是一条慢SQL让你分析为什么没走索引。比如一张千万级订单表按create_time范围查询执行计划显示TABLE ACCESS FULL。最简单的验证方式是EXPLAIN PLAN FOR SELECT * FROM orders WHERE create_time DATE 2025-01-01 AND create_time DATE 2025-02-01; SELECT * FROM TABLE(dbms_xplan.display());如果看到Predicate Information里写了filter而不是access说明索引列被函数包裹或者查询条件类型不匹配。一个典型的误区是索引列上有隐式类型转换-- 错误create_time是DATE类型却和字符串比较 SELECT * FROM orders WHERE create_time 2025-01-01; -- 正确显式转换类型 SELECT * FROM orders WHERE create_time DATE 2025-01-01;对于create_time这种范围查询如果数据量大应该建基于日期列的函数索引或局部索引CREATE INDEX idx_orders_create_time ON orders(create_time) LOCAL;注意这是单机环境LOCAL只适用于分区表。原题里经常会判断“这个索引能不能用”的问题核心就是看执行计划里是不是INDEX RANGE SCAN以及access条件是不是把范围边界传给索引了。4.2 分页查询与dual表的隐藏细节“oracle分页”是高频搜索词也是原题的必考知识点。Oracle没有MySQL的LIMIT分页必须用ROWNUM或OFFSET FETCH。常用写法有两种会踩的坑却不一样。第一种三层嵌套的ROWNUM分页。SELECT * FROM ( SELECT t.*, ROWNUM rn FROM ( SELECT emp_id, emp_name, salary FROM employees ORDER BY salary DESC ) t WHERE ROWNUM 20 ) WHERE rn 10;注意第二层ROWNUM 20是先截断再排序不是——最内层的子查询已经完成排序所以第二层截断的是排序后的前20行。如果内层没有ORDER BY分页结果就没有确定性。第二种更简洁SELECT * FROM employees ORDER BY salary DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;OFFSET FETCH是12c以后引入的19c完全支持底层还是ROWNUM但写法更清晰。原题常设陷阱在OFFSET很大比如十万时数据库仍然会扫描前面所有行不会直接跳过去。所以对于深分页正确优化方式是记住上一页的最后一个值SELECT * FROM employees WHERE salary 8000 ORDER BY salary DESC FETCH NEXT 10 ROWS ONLY;这样才能稳定利用索引跳过前面大量数据。有关dual表的题目考试喜欢问“dual到底多大”。其实只有一行一列结构固定是DUMMY VARCHAR2(1)。由于从19c开始很多系统把dual定义成DUAL并且可以被多个并发查询同时访问不建议往dual表里插数据。如果你需要临时生成多行序列用CONNECT BYSELECT LEVEL, SYSDATE FROM dual CONNECT BY LEVEL 10;4.3 存储过程和case when用对的写法原题里的存储过程重点是异常处理和事务控制。一个典型的需求批量更新员工工资如果某个部门不存在就跳过最后统一提交。CREATE OR REPLACE PROCEDURE batch_update_salary( p_dept_id IN NUMBER, p_increase IN NUMBER ) AS v_emp_count NUMBER; BEGIN SAVEPOINT before_update; -- 设置保存点 UPDATE employees SET salary salary p_increase WHERE dept_id p_dept_id; v_emp_count : SQL%ROWCOUNT; IF v_emp_count 0 THEN ROLLBACK TO before_update; DBMS_OUTPUT.PUT_LINE(No employees in dept || p_dept_id); ELSE COMMIT; DBMS_OUTPUT.PUT_LINE(Updated || v_emp_count || rows); END IF; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END batch_update_salary; /SAVEPOINT在这里的作用是如果跟新行数为0只回滚刚开的这个UPDATE不影响保存点之前的操作。SQL%ROWCOUNT返回上一条DML影响的行数这是存储过程里常用的判断依据。WHEN OTHERS后面必须RAISE或者RAISE_APPLICATION_ERROR否则异常被吞掉而不被调用方感知。CASE WHEN的考点则多在判断条件和NULL的比较上。下面这个写法是错的SELECT CASE WHEN salary ! NULL THEN 有工资 ELSE 无工资 END FROM employees;在Oracle里NULL和任何数字比较都是NULL不会进入THEN分支。正确写法必须是SELECT CASE WHEN salary IS NOT NULL THEN 有工资 WHEN salary IS NULL THEN 无工资 ELSE 未知 END FROM employees;原题通常会在这个地方挖坑尤其是统计分组的场景。另一个更隐蔽的错误是CASE里做多个范围判断时要注意顺序SELECT CASE WHEN salary 5000 THEN 低 WHEN salary 10000 THEN 中 ELSE 高 END AS salary_level FROM employees;如果把WHEN salary 10000放在前面那么工资2000的人会先命中“中”而不是“低”所以条件顺序是有业务逻辑的不是随便排。5. 把PDF第二部分变成可复现的实验室三招验收你的19c环境原题资料里会有很多静态的配置片段和代码块但你永远不知道自己在生产环境里能不能复现。这里提供一个最低成本的验证方法用Podman或Docker跑一个19c容器然后把PDF里的每一条SQL和命令都跑一遍胜过背十遍答案。第一招快速拉起一个19c测试库docker run -d --name oracle19c \ -p 1521:1521 -p 5500:5500 \ -e ORACLE_SIDORCL19C \ -e ORACLE_PDBPDB1 \ -e ORACLE_PWDOracle123 \ -v oracle19c-data:/opt/oracle/oradata \ container-registry.oracle.com/database/enterprise:19.25.0.0.241015启动后等日志出现DATABASE IS READY TO USE再执行docker logs -f oracle19c | tail -1确认。这个镜像会自己创建CDB和PDB和你的本地环境隔离随便折腾也不怕。第二招用一条SQL验证PDF里所有涉及版本和容器的关键参数SELECT name, cdb, open_mode, con_id FROM v$containers ORDER BY con_id;如果cdb返回YES说明数据库以多租户模式创建con_id是容器ID1是CDB$ROOT2是PDB$SEED3通常是你的业务PDB。PDF里凡是涉及到“在哪个容器里执行”的题都能用这个结果判断。第三招针对“原题答案是否正确”的纠结最稳妥的办法是把题目里的SQL改写成可验证的断言。比如某个题说“更新数据后需要commit”你在SQL*Plus里连续执行两次相同更新SET AUTOCOMMIT OFF; UPDATE employees SET salary salary 100 WHERE emp_id 1; SELECT salary FROM employees WHERE emp_id 1; -- 看到当前会话的重做值 ROLLBACK; SELECT salary FROM employees WHERE emp_id 1; -- 确认回滚后恢复原值这样一次实验就同时验证了事务的提交、回滚与会话隔离规则远比死记硬背“DML之后要commit”更扎实。最后留一个非常实用的验收点每次从PDF里学到一个新命令就用它去查你现有生产库或测试库的v$parameter。比如SHOW PARAMETER compatible;确认当前兼容级别是否19.0.0这决定了新特性是否启用。把原题变成环境里的真实输出资料的价值才算真正落地。本文还有配套的精品资源点击获取