原文地址:What does datapatch do when you have different components in PDBs?
原文作者:Patch Recommendation
过去几周,实际上是几周,我花了很多时间处理几个补丁主题。为了稍微清理一下我的收件箱,我会将学习内容转储到几篇博客文章中。今天的这个将是关于我遇到的一个有趣的案例,当时客户在 ExaCC 环境中遇到数据补丁运行时问题。因此,今天的主题是:当 PDB 中有不同的组件时,datapatch 会做什么?
不同的组件?
在多租户环境中,您可以为数据库组件选择各种策略。当您开始创建 CDB 时,只要您输入“高级配置”和“自定义数据库”路径,DBCA 就会为您提供一些选择。
- 请注意 DBCA 中 PDB 的数据库选项选择
- 使用 DBCA 创建多租户数据库 - 须知
- 使用您自己的模板通过 DBCA 创建数据库
许多客户选择了以下策略:
- 拥有 CDB$ROOT 中的所有组件
- 在 PDBSEED 中只有最少的组件集 这种策略会导致新的 PDB 只有最少的组件集。但之后可以在需要时安装可能需要的组件。它还允许插入任何非 CDB,因为所有组件都存在于 CDBROOT 中,因此不会引发冲突。
当您现在比较CDB_REGISTRY中的组件集时(并确保在每个多租户环境中_exclude_seed_cdb_view=false否则您将看不到 PDB$SEED 中的组件),您会发现如下输出:
SQL> select con_id, comp_id, comp_name from cdb_registry order by 1,2; CON_ID COMP_ID COMP_NAME ------ ---------- -------------------------------------------------- 1 CATALOG Oracle Database Catalog Views 1 CATJAVA Oracle Database Java Packages 1 CATPROC Oracle Database Packages and Types 1 JAVAVM JServer JAVA Virtual Machine 1 OLS Oracle Label Security 1 ORDIM Oracle Multimedia 1 OWM Oracle Workspace Manager 1 RAC Oracle Real Application Clusters 1 XDB Oracle XML Database 1 XML Oracle XDK 2 CATALOG Oracle Database Catalog Views 2 CATPROC Oracle Database Packages and Types 2 RAC Oracle Real Application Clusters 2 XDB Oracle XML Database 3 CATALOG Oracle Database Catalog Views 3 CATPROC Oracle Database Packages and Types 3 RAC Oracle Real Application Clusters 3 XDB Oracle XML Database 4 CATALOG Oracle Database Catalog Views 4 CATPROC Oracle Database Packages and Types 4 RAC Oracle Real Application Clusters 4 XDB Oracle XML Database
复制
CDBROOT 的组件比 PDBSEED 和 PDB 多。
这与数据补丁有什么关系?
现在你可能会问自己:这与打补丁有什么关系,尤其是数据补丁?
我承认我也不知道(目前)有关系。我参与了数周的客户案例开始于对数据补丁运行时的投诉。随着从 19.12.0 到 19.13.0 的更改以及多个补丁之一的应用,其中一些与 Data Pump 有关,打补丁的时间明显延长。对于数据泵主题,您可以在接下来的几天阅读另一篇博文。
但是当我们开始挖掘日志文件时,我不知道的事情变得清晰起来:
与 CDB$ROOT 相比,当 PDB 中有不同的组件时,datapatch 采用不同的路线。
而这种不同的路线会导致并行能力的丧失。我知道,这听起来有点奇怪,但如果您对血腥细节感兴趣,请继续阅读。并提前评论:数据补丁团队已经在研究解决方案。它并不像第一眼看上去那么简单。
datapatch的日志结构
让我从日志文件开始这段旅程。我可以告诉你:datapatch 会写很多日志。在具有大量数据库的环境中,随着时间的推移,您的机器上很容易获得一些 GB。您将在以下位置找到所有数据补丁日志:$ORACLE_BASE/cfgtoollogs/sqlpatch
我知道你们中的一些人现在可能会登录到您的数据库服务器并立即检查该目录的大小。但是在清除它之前请记住:当您打开一个抱怨补丁运行时的 SR 时,拥有日志是必不可少的。您可能会整天抱怨数据补丁速度慢 - 但详细信息都在这里。因此,在这种情况下,您可能需要压缩整个目录并将其上传到 MOS。
该子目录的结构如下所示:
$ find . -maxdepth 1 -printf '%TY-%Tm-%Td %TH:%TM %f\n' 2022-01-19 23:16 . 2019-04-18 23:27 sqlpatch_26498_2019_04_18_23_27_00 2022-01-19 23:16 sqlpatch_history.txt 2019-04-18 23:27 29314339 2019-04-18 23:59 sqlpatch_30226_2019_04_18_23_59_24 2019-04-28 00:51 sqlpatch_27456_2019_04_28_00_50_15 2019-04-28 00:50 29517242 2019-10-16 19:42 sqlpatch_8582_2019_10_16_19_40_28 2019-10-16 19:40 30125133 2019-10-16 20:08 sqlpatch_14343_2019_10_16_20_07_36 2019-10-16 20:07 30138470 2019-10-16 20:11 sqlpatch_15340_2019_10_16_20_09_24 2020-01-21 21:23 sqlpatch_16010_2020_01_21_21_20_48 2020-01-21 21:21 30557433 2020-01-21 21:44 sqlpatch_20635_2020_01_21_21_43_12 2020-01-21 21:43 30593149 2020-01-21 21:48 sqlpatch_21868_2020_01_21_21_47_13 2020-04-14 23:50 sqlpatch_12047_2020_04_14_23_49_37 2020-04-14 23:50 30886680 2020-04-14 23:53 sqlpatch_13154_2020_04_14_23_51_50 2020-04-15 00:17 sqlpatch_18226_2020_04_15_00_14_23 2020-04-15 00:16 30869156 2020-07-15 10:29 sqlpatch_13501_2020_07_15_10_25_31 2020-07-15 10:27 31281355 2020-07-15 10:55 sqlpatch_21542_2020_07_15_10_54_08 2020-07-15 10:55 31312468 2020-07-15 11:02 sqlpatch_23127_2020_07_15_11_00_12 2020-10-21 11:33 sqlpatch_9132_2020_10_21_11_32_20 2020-10-21 11:33 31741641 2020-10-21 11:35 sqlpatch_10552_2020_10_21_11_34_42 2020-10-21 11:56 sqlpatch_15467_2020_10_21_11_52_34 2020-10-21 11:55 31771877 2021-01-20 00:33 sqlpatch_11395_2021_01_20_00_33_39 2021-01-20 00:33 32228578 2021-01-20 00:35 sqlpatch_12610_2021_01_20_00_35_03 2021-01-20 01:04 sqlpatch_19749_2021_01_20_01_00_14 2021-01-20 01:00 32218454 2021-04-21 14:43 sqlpatch_2302_2021_04_21_14_40_26 2021-04-21 14:40 32545013 2021-04-21 15:09 sqlpatch_7267_2021_04_21_15_09_24 2021-04-21 15:09 32507738 2021-04-21 15:15 sqlpatch_8871_2021_04_21_15_14_28 2021-08-09 16:06 sqlpatch_16234_2021_08_09_16_04_00 2021-08-09 16:04 32904851 2021-12-15 23:32 sqlpatch_25729_2021_12_15_23_29_47 2021-12-15 23:30 33192793 2021-12-16 00:10 sqlpatch_30410_2021_12_16_00_09_28 2021-12-16 00:09 33192694 2021-12-16 09:08 sqlpatch_13274_2021_12_16_09_08_23 2021-12-16 09:08 33261817 2021-12-16 09:13 sqlpatch_14945_2021_12_16_09_13_21 2022-01-19 21:48 sqlpatch_29286_2022_01_19_21_46_51 2022-01-19 21:47 33515361 2022-01-19 22:14 sqlpatch_485_2022_01_19_22_13_40 2022-01-19 22:14 33561310 2022-01-19 22:25 sqlpatch_4600_2022_01_19_22_25_31 2022-01-19 22:25 33587128 2022-01-19 22:31 sqlpatch_6012_2022_01_19_22_30_32 2022-01-19 23:18 sqlpatch_12220_2022_01_19_23_16_38
复制
这看起来很夸张——但您可能会识别出只有数字的子目录(例如33587128)和以“sqlpatch”开头的子目录(例如sqlpatch_12220_2022_01_19_23_16_38)。上面的清单告诉你我的 19c 环境中的数据补丁历史可以追溯到 2019 年 4 月。名称中包含“ sqlpatch ”的子目录包含特定数据库的数据补丁执行信息:
├── sqlpatch_485_2022_01_19_22_13_40 ├── install1.sql ├── sqlpatch_autorecomp_CDBROOT.log ├── sqlpatch_autorecomp_PDBSEED.log ├── sqlpatch_catcon_0.log ├── sqlpatch_catcon__catcon_485.lst ├── sqlpatch_debug.log ├── sqlpatch_invocation.log ├── sqlpatch_progress.json └── sqlpatch_summary.json
复制
虽然只有数字的子目录包含一个带有补丁 ID 的子目录,但如果它是多租户环境,您将在其中找到每个容器的日志,例如:
[CDB2] oracle@hol:/u01/app/oracle/cfgtoollogs/sqlpatch/33515361/24589353 $ ls 33515361_apply_CDB2_CDBROOT_2022Jan19_21_47_29.log 33515361_apply_CDB2_PDBSEED_2022Jan19_21_47_54.log 33515361_apply_UP19_2022Jan19_23_17_14.log 33515361_ru_apply_CDB2_CDBROOT_2022Jan19_21_47_28.log 33515361_ru_apply_CDB2_PDBSEED_2022Jan19_21_47_53.log 33515361_ru_apply_UP19_2022Jan19_23_17_13.log
复制
在我们的例子中,重要的日志文件是sqlpatch_invocation.log
和install n .sql
,
在sqlpatch_invocation.log 中,我们将找到实际的补丁队列,例如要回滚和应用的补丁以及补丁队列。这个修补队列告诉我们,多租户环境中的容器是并行修补还是串行修补。
并行修补容器,还是仅串行修补?
我们在这个客户案例中发现的是sqlpatch_invocation.log中记录的不同修补队列。
快速数据补丁运行如下所示:
[2022-01-13 18:41:59] Checking prereqs for queue entry for PDBs CDB$ROOT,PDB$SEED,MYPDB1
复制
虽然慢速运行在sqlpatch_invocation.log中有这样的队列:
[2022-01-13 18:40:16] Checking prereqs for queue entry for PDBs CDB$ROOT,PDB$SEED [2022-01-13 18:40:59] Checking prereqs for queue entry for PDBs MYPDB2
复制
你现在可能想知道:问题是什么?
但同时您会在目录中找到一个install1.sql(当您只有一个补丁队列时)或多个文件,例如install1.sql和install2.sql。
因此,甚至无需查看您的sqlpatch_invocation.log,您就可以自行诊断:
目录中只有一个install1.sql ==> 所有容器中的相同组件
您在目录中有一个install1.sql和一个install2.sql ==> PDB 的组件少于 CDBROOT
目录中有超过 2 个安装n.sql ==> PDB在 PDB 之间具有不同的组件,并且组件少于 CDBROOT
但为什么这很重要?
通常,您会期望在多租户环境中并行执行数据补丁操作。通常,它确实并行工作。因此,在上述情况 (a.) 中,您会发现 datapatch 首先在 CDBROOT 中运行所需的操作,然后在包括 PDBSEED 的 PDB 中并行运行。例如,这将导致:
--worker0--CDB$ROOT | |–-worker0––-PDB$SEED |––worker1--–MYPDB1 |––worker2--–MYPDB2
复制
这意味着,一旦 worker 0 使用 CDBROOT 完成,它现在可以使用 PDBSEED 进行,而其他 worker 将同时处理 PDB。如果您问自己可能会启动多少个工人,这取决于核心的数量。并行度算法首先由底层的catcon.pm确定。但是 datapatch 可能会限制它,因为在具有大量 CPU 和许多 PDB 的系统上,您最终可能会遇到太多并行工作程序。在 AutoUpgrade 中,我们做类似的事情并防止超过可用进程的数量。
回到现实来看——与 CDB$ROOT 相比,PDB 中的不同组件我们得到了什么?
--worker0--CDB$ROOT | |–-worker0––-PDB$SEED---MYPDB1---MYPDB2 |––worker1--–
复制
这看起来…非并行但连续。
因此,当您拥有具有各种组件但与 CDB$ROOT 不同的 PDB 时,就会发生这种情况。
这是一个错误吗?
当然,您可能遇到的第一个问题是这是否是一个错误。
它不是。但这显然并不理想。
因此,让我澄清为什么会发生这种情况。
这种行为的原因是与 CDB$ROOT 相比,PDB 中的组件集不同。当 datapatch 需要应用来自 RU 或 RUR 的 SQL 和 PLSQL 更改时,它会查找组件。这个检查的想法很简单,当您的数据库中没有 SDO 时,datapatch 不应该浪费时间来运行例如 SDO 脚本。
因此,通常具有较少选项的数据库不仅升级速度更快,而且修补速度也更快,因为可能会运行更少的脚本。
让我们再次检查sqlpatch_invocation.log,因为它会告诉您事实:
CDBSLOW 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: ', 'pdbs' => [ 'CDB$ROOT', 'PDB$SEED' ] 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: ', 'pdbs' => [ 'PDB$SEED' ] 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: CONTEXT,DV,OLS,SDO,XOQ', 'pdbs' => [ 'MYPDB1' ]
复制
这是从一个缓慢的运行开始的,现在所有的事情都是连续发生的。指示符是 PDB 列表中第一个patch_string末尾缺少的 PDB。在那里您会看到标志“ NO: CONTEXT, DV, OLS, SDO, XOQ ”,这意味着这些组件在 CDBROOT 和 PDBSEED 中,但不在 MYPDB1 中。
只需将其与并行化的快速运行进行比较:
CDBFAST 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: ', 'pdbs' => [ 'CDB$ROOT', 'PDB$SEED', 'MYPDB1' ] 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: ', 'pdbs' => [ 'PDB$SEED' ] 'patch_string' => 'IR: 32876380/24269510 29213893/24262223 29309073/24433914 33027539/24390892 33144001/24351857 33502645/24472857 IA: 33192694/24421575 29213893/24384541 29309073/24493062 33721661/24575622 RI: 33192793/24462514 19.12.0.0.0 Release_Update 210716141810 NO: ', 'pdbs' => [ 'MYPDB2' ]
复制
“ NO: ”标志中有一个空字符串。组件在任何地方都是相同的,不需要排除任何东西。
该主题在非公开BUG 33089192 – MOVE SET_FILE_METADATA FROM CHECK_QUEUE_PREREQS下得到跟踪和修复。数据补丁团队正在努力,但我不能给你一个估计。
解决方法
您如何解决此问题?
当您使用opatchauto时,没有解决方法,因为opatchauto是一个不允许您跳过任何步骤的编排。甚至在常规opatch运行后调用 datapatch也无济于事,因为它将以相同的方式建立其队列。
所以基本上,在 datapatch 选择更好的策略之前,真正的解决方案是在所有容器中安装相同的组件。而且我知道这不是我们可以在这里讨论的真正解决方法。
因此,没有真正的解决方法可用。
这也会影响普通补丁吗?
您很可能不会在普通补丁中看到这种模式,因为它们通常不会访问各种组件。我只看到了 RU 和 RUR。
总结一下
只有当您拥有多租户环境时,您才会对我所写的主题感兴趣。如果您的 PDB 在 CDB_REGISTRY 中设置的组件与 CDB$ROOT 不同,则 datapatch 将建立独立的补丁队列以避免运行可能适用于一个或多个 PDB 中不存在的组件的补丁脚本。不幸的是,在这种情况下,datapatch 现在串行执行修补,一个接一个容器,而不是许多 PDB 与独立工作人员并行执行。因此,在这种情况下,您不会从系统的并行功能中受益。并且数据补丁运行可能需要更长的时间。
这种效果在单租户环境中最为明显,您希望 PDBSEED 和 PDB 被并行处理,但现在却一个接一个地修补。CDBROOT 总是首先打补丁,没有预期的并行活动。
未来将增强 Datapatch 以适应此类情况并利用并行功能。