Oracle Database Cloud ServiceにおけるSPFILEの復旧

- SPFILEに不正な値が設定されてインスタンスが起動しなくなったときの復旧手順
- DBCSのSPFILEはASM管理領域にあり
- srvctlを利用したデータベース構成の変更

# はじめに
Oracle Database Cloud Service (DBCS) において、本番環境ではストレージ管理ソフトウェアに「Oracle Grid Infrastructure」を選択されることが推奨されています。Oracle Grid Infrastructureを利用して作成されたDBシステムでは、ディスク領域管理にASM (Automatic Storage Management) が使われ、Oracle Databaseの初期化パラメータを格納するサーバ・パラメータ・ファイル (SPFILE) もASM管理領域に配置されています。
本記事では。人為的なミス等によってSPFILEの初期化パラメータに不正な値が書き込まれ、Oracle Databaseインスタンスが起動しなくなった障害を想定し、SPFILEの復旧手順について記します。

# 検証環境 
- DBシステム・バージョン: 19.14.0.0.0
- Oデータベース・バージョン: 19.14.0.0.0
- Oracle Databaseソフトウェア・エディション: Standard Edition
- ストレージ管理ソフトウェア: Oracle Grid Infrastructure


# 障害発生状況の再現
アーカイブ・ログの格納先に誤ったディレクトリ・パスを指定してしまいORA-16032が発生した状況を再現したいと思います。
作成済のDBCSインスタンスにopcユーザーでSSHでログインし、oracleユーザーに変更して作業を行います。

```shell-session:
$ sudo su - oracle
```

SQLPlusを起動して、まずはLOG_ARCHIVE_DEST_1のデフォルト値を確認しておきます。

```shell-session:
$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Apr 15 14:57:53 2022
Version 19.14.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.14.0.0.0

SQL> set pages 10
SQL> set line 100
SQL> column dest_id format "99"
SQL> column dest_name format a30
SQL> column destination format a60
SQL> select dest_id,dest_name,destination from v$archive_dest where dest_id=1 or dest_id=2;

DEST_ID DEST_NAME		       DESTINATION
------- ------------------------------ ------------------------------------------------------------
      1 LOG_ARCHIVE_DEST_1	       USE_DB_RECOVERY_FILE_DEST
      2 LOG_ARCHIVE_DEST_2

SQL>
```

alter systemコマンドでlog_archive_dest_1を不正な値に書き換えます。ここではscopeにspfileを指定しているため、即時に設定は反映されないです。

```shell-session:
SQL> alter system set log_archive_dest_1='location=/u03/' scope=spfile;

System altered.

SQL> select dest_id,dest_name,destination from v$archive_dest where dest_id=1 or dest_id=2;

DEST_ID DEST_NAME		       DESTINATION
------- ------------------------------ ------------------------------------------------------------
      1 LOG_ARCHIVE_DEST_1	       USE_DB_RECOVERY_FILE_DEST
      2 LOG_ARCHIVE_DEST_2

SQL>
```

Oracleを再起動してみましょう。

```shell-session:
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup 
ORA-16032: parameter LOG_ARCHIVE_DEST_1 destination string cannot be translated
ORA-07286: sksagdi: cannot obtain device information.
Linux-x86_64 Error: 2: No such file or directory
SQL> startup nomount 
ORA-16032: parameter LOG_ARCHIVE_DEST_1 destination string cannot be translated
ORA-07286: sksagdi: cannot obtain device information.
Linux-x86_64 Error: 2: No such file or directory
SQL> 
```

ORA-16032が発生してNOMOUNTでも起動しない状態になりました。この状態から復旧していきたいと思います。

# 復旧作業
## OCR情報の確認
作業で利用するOCR情報を確認しておきます。
まず一意のデータベース名を取得します。

```shell-session:
$ srvctl config database
DB0318_nrt1pz
```
取得された一意のデータベース名を利用してOCRに登録されている情報を確認しておきます。

```shell-session:
$ srvctl config database -d DB0318_nrt1pz -a
Database unique name: DB0318_nrt1pz
Database name: DB0318
Oracle home: /u01/app/oracle/product/19.0.0.0/dbhome_1
Oracle user: oracle
Spfile: +DATA/DB0318_NRT1PZ/PARAMETERFILE/spfile.267.1099660635
Password file: 
（省略）
```
データベース名や復旧したいSPFILEが格納されたASM内のディレクトリを確認できました。

## 仮のPFILEを利用してインスタンス起動
Oracle Databaseのインスタンを起動できるようにするために仮のPFILEを作成します。db_nameにはデータベース名（一意のデータベースではない）を設定します。

```shell-session:
$ cat $ORACLE_HOME/dbs/init_temp.ora
db_name=DB0318
large_pool_size=100m
shared_pool_size=400m
db_cache_size=100m
```
SQLPlusから、仮のPFILEを利用してNOMOUNTでOracleの起動を試みます。

```shell-session:
$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Apr 15 17:25:16 2022
Version 19.14.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup nomount pfile='$ORACLE_HOME/dbs/init_temp.ora';
ORACLE instance started.

Total System Global Area  650116224 bytes
Fixed Size		    8899712 bytes
Variable Size		  528482304 bytes
Database Buffers	  104857600 bytes
Redo Buffers		    7876608 bytes
SQL> 
```
仮のPFILEを利用してNOMOUNT状態でOracleインスタンスを起動できました。

## ASM内のSPFILEからPFILE作成し、問題箇所を修正
事前に確認しておいたSPFILEが格納されたASM内のディレクトリ・パスを利用してオリジナルのSPFILEよりPFILEを作成します。作成後、仮のOracleインスタンスを停止しておきます。

```shell-session:
SQL> CREATE PFILE = '$ORACLE_HOME/dbs/init_from_sp.ora' FROM SPFILE='+DATA/DB0318_NRT1PZ/PARAMETERFILE/spfile.267.1099660635';

File created.

SQL> shutdown immediate;
ORA-01507: database not mounted


ORACLE instance shut down.
SQL>
```

SPFILEより作成したPFILEの問題箇所を修正します。
今回のケースですと、下記の行を、

```shell-session:
*.log_archive_dest_1='location=/u03/'
```
元の設定値に戻すために削除します。



## SPFILE再作成
修正したPFILEからインスタンス起動し、SPFILEの再作成を行います。
```shell-session:
$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Apr 15 17:55:31 2022
Version 19.14.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup nomount pfile='$ORACLE_HOME/dbs/init_from_sp.ora';
ORACLE instance started.

Total System Global Area 1.4496E+10 bytes
Fixed Size		    9151688 bytes
Variable Size		 1207959552 bytes
Database Buffers	 1.3254E+10 bytes
Redo Buffers		   24399872 bytes

SQL> create spfile from pfile='$ORACLE_HOME/dbs/init_from_sp.ora';

File created.

SQL> shutdown immediate
ORA-01507: database not mounted


ORACLE instance shut down.
SQL> 
```

## ASM管理領域内に作成されたSPFILEの確認
opcユーザーよりgridユーザーに切り替えてasmcmdを利用して確認します。

```shell-session:
$ sudo su - grid
$ asmcmd -p
ASMCMD [+] > ls -l +DATA/DB0318_NRT1PZ/PARAMETERFILE/
Type           Redund  Striped  Time             Sys  Name
PARAMETERFILE  UNPROT  COARSE   APR 15 17:00:00  Y    spfile.267.1099660635
PARAMETERFILE  UNPROT  COARSE   APR 15 17:00:00  Y    spfile.271.1102096597
ASMCMD [+] > 
```
新しくspfile.271.1102096597が作成されていることが確認できます。

## OCR内のSPFILE情報変更
再度oracleユーザーでログインし、OCRに登録されているSPFILEの情報を変更します。

```shell-session:
$ sudo su - oracle
$ srvctl modify database -d DB0318_nrt1pz -p '+DATA/DB0318_NRT1PZ/PARAMETERFILE/spfile.271.1102096597'
```

OCR情報を確認して新しく作成したspfile.271.1102096597が登録されていることを確認します。

```shell-session:
$ srvctl config database -d DB0318_nrt1pz -a
Database unique name: DB0318_nrt1pz
Database name: DB0318
Oracle home: /u01/app/oracle/product/19.0.0.0/dbhome_1
Oracle user: oracle
Spfile: +DATA/DB0318_NRT1PZ/PARAMETERFILE/spfile.271.1102096597
Password file: 
(省略)
```

不要になったPFILEを削除します。
```shell-session:
$ rm $ORACLE_HOME/dbs/init_from_sp.ora
$ rm $ORACLE_HOME/dbs/init_temp.ora   
```

## 新しいSPFILEよりOracleインスタンス起動、SPFILE確認
最後に新しいSPFILEでOracleインスタンスが起動し、データベースをOpen出来ることを確認します。

```shell-session:
$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Apr 15 18:18:34 2022
Version 19.14.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area 1.4496E+10 bytes
Fixed Size		    9151688 bytes
Variable Size		 1207959552 bytes
Database Buffers	 1.3254E+10 bytes
Redo Buffers		   24399872 bytes
Database mounted.
Database opened.
SQL> set pages 10
SQL> set line 100
SQL> SHOW PARAMETER SPFILE;

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
spfile				     string	 +DATA/DB0318_NRT1PZ/PARAMETERF
						 ILE/spfile.271.1102096597
SQL> 
```
新しいspfile.271.1102096597を利用してデータベースをOpenできたことが確認できました。最後にsrvctlを利用してOracleを再起動しておきます。

```shell-session:
$ srvctl stop database -db DB0318_nrt1pz -stopoption immediate -verbose
$ srvctl start database -db DB0318_nrt1pz -verbose
$ srvctl status database -db DB0318_nrt1pz
Instance DB0318 is running on node dbcs
```

おつかれさまでした。以上となります。