Oracle Databaseで特定の不具合が発生した場合、Release Update(RU)の公開を待たずに「個別パッチ」を適用することがあります。
個別パッチは、特定の不具合、Oracle Databaseのバージョン、OS・プラットフォームの組合せに対して提供されるパッチです。「ワンオフ・パッチ」または「Interim Patch」と呼ばれることもあります。
Oracle社は個別パッチをリアクティブ・メンテナンスに分類しており、特定の問題へ対処するためにオンデマンドで提供しています。また、個別パッチに含まれる修正が、後からRUに取り込まれることもあります。
本記事では、Oracle Database 19cのシングル・インスタンス環境に個別パッチを適用する基本的な手順と、複数の個別パッチをまとめて適用するopatch napplyコマンドについて解説します。
本記事の対象環境
本記事では、次の環境を想定しています。
OS :Linux
Oracle Database :Oracle Database 19c
構成 :シングル・インスタンス
Grid Infrastructure :なし
Oracle Restart :なし
適用対象 :Databaseホーム用の個別パッチ
適用ツール :OPatch
次の環境は対象外です。
・Oracle RAC
・Oracle Restart
・Grid Infrastructure
・Data Guard
・Exadata
・Windows
・Oracle JavaVMなど、専用手順が指定されたパッチ
実際の適用方法はパッチによって異なるため、本記事よりも、ダウンロードした個別パッチに付属するREADMEを優先してください。
Oracle社のOPatchマニュアルでも、パッチを適用する前にREADMEの特別な指示を必ず確認するよう案内されています。
個別パッチとRUの違い
RUと個別パッチでは、提供される目的が異なります。
【Release Update】
複数の重要な修正
セキュリティ修正
オプティマイザ修正
機能に関する修正
↓
累積的なパッチとして定期提供
【個別パッチ】
特定の不具合
特定のバージョン
特定のプラットフォーム
↓
必要な環境に個別提供
RUは、多数の修正をまとめた累積的なパッチです。
一方、個別パッチは、特定の不具合を修正するために提供されます。
たとえば、Oracle Database 19.20向けに作成された個別パッチを、Oracle Database 19.25へそのまま適用できるとは限りません。
個別パッチをダウンロードするときは、少なくとも次の組合せを確認する必要があります。
・Oracle Databaseのバージョン
・現在適用されているRU
・OSとプラットフォーム
・対象コンポーネント
・必要なOPatchバージョン
個別パッチは、「不具合・バージョン・プラットフォーム」の組合せに対して提供されるため、現在の環境に対応したパッチを取得することが重要です。
applyとnapplyの違い
個別パッチを適用するときは、主にapplyまたはnapplyを使用します。
opatch apply
└─1つのパッチを適用する
opatch napply
└─複数のパッチをまとめて適用する
applyコマンド
applyは、通常、1つの個別パッチをOracleホームへ適用するときに使用します。
opatch apply <パッチディレクトリ>
Oracle社のOPatchマニュアルでも、単一パッチの適用例として次の形式が示されています。
opatch apply /tmp/patch/12345678
パッチディレクトリへ移動して実行することもできます。
cd /u01/stage/oneoff/12345678
$ORACLE_HOME/OPatch/opatch apply
napplyコマンド
napplyは、複数の個別パッチを一度のコマンドで適用するときに使用します。
Oracle社のコマンドリファレンスでは、napplyは「n個のパッチをインストールするコマンド」と説明されています。システム・パッチには対応していないため、基本的には複数の個別パッチを対象として使用します。
基本構文は次のとおりです。
opatch napply <複数のパッチを格納したディレクトリ>
napplyについては、後半で詳しく解説します。
個別パッチ適用の全体的な流れ
基本的な流れは次のとおりです。
個別パッチを入手
↓
READMEを確認
↓
OPatchのバージョン確認
↓
現在のパッチ状態を確認
↓
競合チェック
↓
DB・リスナー停止
↓
opatch apply
↓
DB・PDB起動
↓
必要に応じてdatapatch
↓
適用結果確認
個別パッチによっては、データベースを停止せずに適用できるオンライン・パッチもあります。
ただし、すべての個別パッチがオンライン適用に対応しているわけではありません。READMEにオンライン適用可能と明記されていない場合は、通常どおりデータベースとリスナーを停止して適用します。
1.個別パッチを入手する
個別パッチはMy Oracle Supportから入手します。
Oracle Supportからパッチ番号を案内されている場合は、そのパッチ番号を使用して検索します。
本記事では、個別パッチの番号を次のように表記します。
<PATCH_ID>
例として、パッチ番号を12345678とします。
ダウンロードしたファイル名の例は次のとおりです。
p12345678_190000_Linux-x86-64.zip
ダウンロード時には、対象プラットフォームが正しいことを確認します。
パッチ番号 :12345678
Oracleバージョン :19c
プラットフォーム :Linux x86-64
同じパッチ番号でも、Oracle Databaseのバージョンやプラットフォームが異なるファイルが提供されることがあります。
2.READMEを確認する
ダウンロードした個別パッチには、READMEが含まれています。
READMEでは、主に次の内容を確認します。
・対象製品とバージョン
・適用可能なRU
・必要なOPatchバージョン
・競合するパッチ
・データベース停止の要否
・opatchの実行方法
・datapatchの実行要否
・個別のSQL実行要否
・ロールバック方法
・既知の問題
特に重要なのが、現在のRUに対応した個別パッチであるかどうかです。
たとえば、現在のOracle Databaseが19.25であるにもかかわらず、19.23向けに作成された個別パッチを取得しても、正常に適用できない可能性があります。
3.Oracle環境変数を設定する
Oracleソフトウェア所有者でログインします。
su - oracle
環境変数を設定します。
export ORACLE_SID=ORCL
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export PATH=$ORACLE_HOME/OPatch:$ORACLE_HOME/bin:$PATH
設定内容を確認します。
echo $ORACLE_SID
echo $ORACLE_HOME
which opatch
which sqlplus
実行例は次のとおりです。
/u01/app/oracle/product/19.0.0/dbhome_1/OPatch/opatch
/u01/app/oracle/product/19.0.0/dbhome_1/bin/sqlplus
複数のOracleホームが存在する環境では、適用対象のOracleホームが正しく設定されていることを必ず確認してください。
OPatchは、環境変数ORACLE_HOMEに設定されたOracleホームを処理対象として使用します。
4.OPatchのバージョンを確認する
次のコマンドを実行します。
$ORACLE_HOME/OPatch/opatch version
出力例は次のとおりです。
OPatch Version: 12.2.0.1.xx
表示されたOPatchのバージョンが、個別パッチのREADMEに記載されている要件を満たしていることを確認します。
要件を満たしていない場合は、My Oracle SupportからOracle Database 19c用のOPatchを入手して更新します。
OPatchの代表的なパッチ番号は6880880ですが、ダウンロード時には対象バージョンとプラットフォームを必ず確認してください。
5.現在のパッチ状態を確認する
Oracleホームに適用されているパッチを確認します。
$ORACLE_HOME/OPatch/opatch lsinventory
簡易的な一覧を確認する場合は、lspatchesを使用します。
$ORACLE_HOME/OPatch/opatch lspatches
結果をファイルへ保存しておくと、適用前後を比較できます。
mkdir -p /u01/work/patch_log
$ORACLE_HOME/OPatch/opatch lsinventory -detail \
> /u01/work/patch_log/lsinventory_before.txt
OPatchを使用した一般的なパッチ適用では、最初にlsinventoryで現在インストールされている内容を確認し、適用後にも再度確認する流れが示されています。
6.個別パッチを展開する
パッチを配置するディレクトリを作成します。
mkdir -p /u01/stage/oneoff
cd /u01/stage/oneoff
個別パッチを展開します。
unzip p12345678_190000_Linux-x86-64.zip
展開後のディレクトリを確認します。
ls -l
例として、次のような構成になります。
/u01/stage/oneoff/
└── 12345678
├── README.html
├── etc
└── files
パッチのディレクトリ構成は、実際のパッチによって異なる可能性があります。
7.既存パッチとの競合を確認する
個別パッチを適用する前に、Oracleホームに適用済みのパッチと競合しないか確認します。
パッチディレクトリへ移動します。
cd /u01/stage/oneoff/12345678
次のコマンドを実行します。
$ORACLE_HOME/OPatch/opatch \
prereq CheckConflictAgainstOHWithDetail -ph ./
CheckConflictAgainstOHWithDetailは、適用予定のパッチとOracleホームに適用済みのパッチとの競合を確認し、競合やスーパーセットに関する詳細を表示します。
競合が検出された場合は、そのままopatch applyを実行してはいけません。
主に次の対応を検討します。
・現在のRUに対応した個別パッチを取得する
・既存の個別パッチをロールバックする
・複数の修正を含むマージパッチを取得する
・対象の修正が現在のRUに含まれているか確認する
・Oracle Supportへ対応方法を確認する
パッチ同士が同じファイルへ別々の変更を加える場合、競合として検出されることがあります。
Oracle社は、手順だけでは競合を解決できない場合、My Oracle Supportへ問い合わせてマージパッチを取得する方法を案内しています。
8.データベースとリスナーを停止する
個別パッチのREADMEで停止が必要とされている場合は、データベースへ接続するアプリケーションやバッチ処理を停止します。
データベースを停止します。
sqlplus / as sysdba
SHUTDOWN IMMEDIATE;
EXIT;
リスナーを停止します。
lsnrctl stop
対象のOracleプロセスが残っていないことを確認します。
ps -ef | grep -v grep | grep "$ORACLE_HOME"
ps -ef | grep -v grep | grep ora_
個別パッチがオンライン適用に対応している場合は、停止方法が異なる可能性があります。READMEに記載された手順を使用してください。
9.applyコマンドで個別パッチを適用する
パッチディレクトリへ移動します。
cd /u01/stage/oneoff/12345678
個別パッチを適用します。
$ORACLE_HOME/OPatch/opatch apply
パッチディレクトリを引数として指定することもできます。
$ORACLE_HOME/OPatch/opatch apply \
/u01/stage/oneoff/12345678
Oracle社のOPatchマニュアルでも、単一パッチはopatch apply <パッチディレクトリ>の形式で適用する例が示されています。
正常終了した場合は、最後に次のメッセージが表示されます。
OPatch succeeded.
エラーが表示された場合は、出力されたOPatchログを確認します。
10.個別パッチの適用結果を確認する
Oracleホームのパッチ一覧を確認します。
$ORACLE_HOME/OPatch/opatch lspatches
詳細を確認する場合は、次のコマンドを実行します。
$ORACLE_HOME/OPatch/opatch lsinventory
適用したパッチ番号が表示されていることを確認します。
12345678;ONE-OFF: FIX FOR BUG 12345678
結果をファイルへ保存します。
$ORACLE_HOME/OPatch/opatch lsinventory -detail \
> /u01/work/patch_log/lsinventory_after.txt
個別パッチがバイナリのみを変更する場合は、opatch lsinventoryまたはopatch lspatchesによる確認が基本です。
11.データベースとPDBを起動する
データベースを起動します。
sqlplus / as sysdba
STARTUP;
CDB環境の場合は、PDBをオープンします。
ALTER PLUGGABLE DATABASE ALL OPEN;
PDBの状態を確認します。
SET LINESIZE 200
SELECT name,
open_mode
FROM v$pdbs
ORDER BY con_id;
12.必要に応じてdatapatchを実行する
個別パッチには、次の2種類があります。
個別パッチ
│
├─バイナリ変更のみ
│ └─OPatchによる適用
│
└─SQL変更を含む
├─OPatchによるバイナリ適用
└─datapatchによるSQL適用
SQLスクリプトを含む個別パッチでは、OPatch実行後にdatapatchが必要です。
DBA_REGISTRY_SQLPATCHには、OPatch完了後にSQLスクリプトを実行する必要があるSQLパッチの情報が記録され、datapatchによって更新されます。
READMEにdatapatchの実行が指定されている場合は、次のように実行します。
cd $ORACLE_HOME/OPatch
./datapatch -verbose
CDB環境では、datapatch実行前に対象PDBをオープンしておきます。
datapatch実行後は、次のSQLで結果を確認します。
SET LINESIZE 250
SET PAGESIZE 100
COLUMN status FORMAT A15
COLUMN description FORMAT A80
SELECT patch_id,
patch_type,
action,
status,
action_time,
description
FROM dba_registry_sqlpatch
ORDER BY action_time;
SQL変更を含む個別パッチであれば、対象パッチについて次のような状態を確認します。
ACTION :APPLY
STATUS :SUCCESS
バイナリ変更のみの個別パッチは、DBA_REGISTRY_SQLPATCHに記録されないことがあります。
そのため、個別パッチの最終的な適用確認では、DBA_REGISTRY_SQLPATCHだけでなく、必ずopatch lsinventoryも確認してください。
napplyコマンドで複数の個別パッチを適用する
ここからは、複数の個別パッチをまとめて適用するnapplyについて解説します。
たとえば、次の3つの個別パッチを適用するとします。
/u01/stage/oneoff/
├── 12345678
├── 23456789
└── 34567890
applyを使用する場合は、それぞれのパッチに対して個別にコマンドを実行します。
opatch apply /u01/stage/oneoff/12345678
opatch apply /u01/stage/oneoff/23456789
opatch apply /u01/stage/oneoff/34567890
napplyを使用すると、親ディレクトリを指定して複数のパッチを一度に処理できます。
$ORACLE_HOME/OPatch/opatch napply \
/u01/stage/oneoff
Oracle社のコマンドリファレンスでは、指定したパッチ格納ディレクトリ配下に存在するすべてのパッチを適用する例として、次の形式が示されています。
opatch napply <patch_location>
napply実行前の競合確認
複数の個別パッチを適用する場合は、2種類の競合を確認します。
確認1
個別パッチとOracleホームの競合
確認2
適用する個別パッチ同士の競合
Oracleホームとの競合を確認する
$ORACLE_HOME/OPatch/opatch prereq \
CheckConflictAgainstOHWithDetail \
-phBaseDir /u01/stage/oneoff
個別パッチ同士の競合を確認する
$ORACLE_HOME/OPatch/opatch prereq \
CheckConflictAmongPatchesWithDetail \
-phBaseDir /u01/stage/oneoff
CheckConflictAmongPatchesWithDetailは、これから適用する複数のパッチ間に競合がないかを確認し、詳細な競合情報を表示するための前提条件チェックです。
いずれかのチェックで競合が検出された場合は、napplyを実行せず、マージパッチの取得などを検討します。
ディレクトリ内の全パッチを適用する
親ディレクトリ配下のパッチをすべて適用する場合は、次のように実行します。
$ORACLE_HOME/OPatch/opatch napply \
/u01/stage/oneoff
ただし、対象ディレクトリには、適用対象ではないパッチやREADMEなどを無秩序に配置しないようにしてください。
napply専用のディレクトリを作成し、今回適用するパッチだけを配置すると分かりやすくなります。
/u01/stage/napply_202608/
├── 12345678
├── 23456789
└── 34567890
$ORACLE_HOME/OPatch/opatch napply \
/u01/stage/napply_202608
パッチIDを指定して適用する
ディレクトリ内の一部のパッチだけを適用する場合は、-idを使用します。
$ORACLE_HOME/OPatch/opatch napply \
/u01/stage/oneoff \
-id 12345678,23456789
この例では、次の2つだけを適用します。
12345678
23456789
34567890は適用されません。
Oracle社のコマンドリファレンスでも、カンマ区切りのパッチIDを指定して、親ディレクトリ配下の一部のパッチを選択する構文が示されています。
重複パッチとサブセットを除外する
napplyには、重複したパッチやサブセットとなるパッチを除外するオプションがあります。
$ORACLE_HOME/OPatch/opatch napply \
/u01/stage/oneoff \
-skip_duplicate \
-skip_subset
skip_duplicate
-skip_duplicateは、Oracleホームに適用済みのパッチと同じ修正内容を持つ重複パッチを省略します。
skip_subset
-skip_subsetは、すでに適用されている別のパッチが、対象パッチの修正内容をすべて含んでいる場合に、そのサブセットとなるパッチを省略します。
Oracle社のコマンドリファレンスでは、次の形式が例として示されています。
opatch napply <patch_location> \
-skip_subset \
-skip_duplicate
これらのオプションは、不要なパッチを自動的に省略できる点では便利です。
ただし、「省略されたから問題ない」と機械的に判断するのではなく、OPatchの出力を確認し、意図した修正が残っているか確認してください。
テキストファイルでパッチを指定する
複数のパッチが別々のディレクトリに配置されている場合は、パッチの場所を記載したテキストファイルを使用できます。
次のファイルを作成します。
vi /u01/stage/patches.txt
パッチディレクトリを1行ずつ記載します。
/u01/stage/oneoff/12345678
/u02/patch/23456789
/u03/work/34567890
次のコマンドで適用します。
$ORACLE_HOME/OPatch/opatch napply - \
-phBaseFile /u01/stage/patches.txt
Oracle社のOPatchマニュアルでも、各パッチの場所を1行ずつ記載したテキストファイルを作成し、-phBaseFileで複数パッチを適用する方法が示されています。
forceオプションは安易に使用しない
napplyには-forceオプションがあります。
opatch napply <patch_location> -force
-forceを指定すると、競合する既存パッチをロールバックしてから、新しいパッチを適用する場合があります。
その結果、既存パッチに含まれていた修正が失われる可能性があります。
Oracle社のOPatchマニュアルでも、-forceによって競合するパッチを削除すると、そのパッチに含まれていた不具合修正を失う可能性があると注意されています。
競合パッチA
└─不具合1を修正
適用するパッチB
└─不具合2を修正
-forceでパッチAを削除
↓
不具合2は修正される
不具合1の修正は失われる可能性
競合が発生した場合は、-forceで強制的に進めるのではなく、原則としてマージパッチの取得やOracle Supportへの確認を優先してください。
個別パッチのロールバック方法
個別パッチをロールバックする場合は、READMEに記載された手順を確認します。
一般的には、データベースとリスナーを停止した後、次のコマンドを実行します。
$ORACLE_HOME/OPatch/opatch rollback \
-id 12345678
OPatchはパッチ適用時に変更前のファイルを$ORACLE_HOME/.patch_storageへ保存し、ロールバック時にそのファイルを使用します。
ロールバック後は、Oracleホームの状態を確認します。
$ORACLE_HOME/OPatch/opatch lspatches
$ORACLE_HOME/OPatch/opatch lsinventory
SQL変更を含む個別パッチをロールバックした場合は、READMEの指示に従ってdatapatchを実行します。
cd $ORACLE_HOME/OPatch
./datapatch -verbose
複数のパッチをロールバックする
複数の個別パッチをまとめてロールバックする場合は、nrollbackを使用できます。
$ORACLE_HOME/OPatch/opatch nrollback \
-id 12345678,23456789
ロールバックする順序や依存関係によっては、そのまま実行できないことがあります。
特に、後から適用したパッチが以前のパッチへ依存している場合は注意が必要です。実際のロールバックでは、各パッチのREADMEとOPatchの前提条件チェック結果を確認してください。
個別パッチ適用時の注意点
現在のRUに対応したパッチを使用する
個別パッチは、特定のRUを前提として作成されている場合があります。
RUを更新した後に同じ個別パッチが必要な場合は、新しいRU向けに作成された個別パッチまたはマージパッチを取得します。
複数パッチはパッチ同士の競合も確認する
単一パッチではOracleホームとの競合確認が中心になります。
複数パッチをnapplyで適用する場合は、Oracleホームとの競合に加えて、適用対象のパッチ同士の競合も確認する必要があります。
単一パッチ
└─Oracleホームとの競合確認
複数パッチ
├─Oracleホームとの競合確認
└─個別パッチ同士の競合確認
DBA_REGISTRY_SQLPATCHだけで判断しない
DBA_REGISTRY_SQLPATCHは、SQLスクリプトを含むパッチの適用履歴を確認するビューです。
バイナリのみを変更する個別パッチは、同ビューに記録されないことがあります。
個別パッチの適用結果は、基本的に次のコマンドで確認します。
opatch lspatches
opatch lsinventory
SQL変更を含む場合は、追加でDBA_REGISTRY_SQLPATCHを確認します。
まとめ
Oracle Database 19cへ個別パッチを適用する基本的な流れは次のとおりです。
個別パッチを入手
↓
READMEを確認
↓
競合チェック
↓
DB・リスナー停止
↓
opatch apply
↓
DB・PDB起動
↓
必要に応じてdatapatch
↓
lsinventoryで確認
1つの個別パッチを適用する場合は、applyを使用します。
opatch apply <パッチディレクトリ>
複数の個別パッチをまとめて適用する場合は、napplyを使用します。
opatch napply <複数パッチの格納ディレクトリ>
一部のパッチだけを選択する場合は、-idを使用します。
opatch napply <パッチ格納ディレクトリ> \
-id 12345678,23456789
個別パッチでは、現在のRU、OS、プラットフォームに対応したパッチを使用することが重要です。
また、複数の個別パッチを適用する場合は、既存パッチとの競合だけでなく、適用する個別パッチ同士の競合も事前に確認してください。
実際の作業では、必ず対象パッチのREADMEを確認し、適用条件、停止方法、datapatchの要否、ロールバック方法に従って作業を行いましょう。
[参考]
Oracle Database Oracle Databaseパッチ・メンテナンス, リリース19c以降のリリース

コメント