マルチスレッドOracle Databaseプロセス・モデルを試す (Oracle Database 12c)

  UNIX/Linux版のOracle Databaseインスタンスは伝統的にプロセス・モデルを使っています。バックグラウンド・プロセスやサーバー・プロセスは、Linux/Unixのプロセスとマップされます（Windows版はスレッド・モデル）。Oracle Database 12cでは、マルチスレッド・モデルを使ってインスタンスを構成するプロセスをスレッド化することができるようになりました。
ただし、インスタンス全体が単一のプロセスとして稼働するわけではなく、いくつかのプロセスにグループ化されて動作します。

マニュアルのプロセス・モデルの説明は[こちら](https://docs.oracle.com/cd/E96517_01/cncpt/process-architecture.html)。
検証はOracle Database 18cで実施しています。

# スレッド・モデルへの移行
プロセス・モデルをスレッド・モデルに変更する場合は、初期化パラメーターthreaded_executionをTRUEに変更します。動的に変更できないため、インスタンスの再起動が必要です。

```
SQL> ALTER SYSTEM SET threaded_execution = TRUE SCOPE=SPFILE;

System altered.
```
初期化パラメーターthreaded_executionの説明は[こちら](https://docs.oracle.com/cd/E96517_01/refrn/THREADED_EXECUTION.html)。

クライアントがリスナー経由で接続する場合には、リスナーのパラメーターDEDICATED_THROUGH_BROKER_{リスナー名}をONに指定する必要があるとマニュアルに記載されています。
試してみたところOFF（デフォルト値）のままでも接続自体はできるようですが、従来通り独立したサーバー・プロセスが起動します。

下記は、マルチスレッド化したOracle Database 18cインスタンスのプロセス状態です。O18Aはインスタンス名です。

```
$ ps -ef | grep ora_ | grep -v grep
oracle    74390      1  0 17:41 ?        00:00:00 ora_pmon_O18A
oracle    74392      1  0 17:41 ?        00:00:01 ora_u002_O18A
oracle    74395      1  0 17:41 ?        00:00:00 ora_psp0_O18A
oracle    74399      1  1 17:41 ?        00:00:06 ora_vktm_O18A
oracle    74406      1  0 17:41 ?        00:00:00 ora_gen1_O18A
oracle    74409      1  2 17:41 ?        00:00:09 ora_u006_O18A
oracle    74412      1  0 17:41 ?        00:00:00 ora_ofsd_O18A
oracle    74420      1  0 17:41 ?        00:00:00 ora_dbw0_O18A
oracle    74422      1  0 17:41 ?        00:00:00 ora_lgwr_O18A
$
```

# プロセスとスレッドの構成
スレッド化されたインスタンスは複数のプロセスから構成されます。それぞれのプロセスには複数のスレッドが構成されています。V$PROCESSビューのSPID列には、OSのプロセスIDが格納されるため、各プロセスが持つスレッド数を確認していみます。
いくつかのプロセスはスレッド化されておらず、プロセスとして動作していることがわかります。

```
SQL> SELECT SPID, COUNT(*) FROM V$PROCESS GROUP BY SPID ORDER BY 1;

SPID                       COUNT(*)
------------------------ ----------
74390                             1
74392                             9
74395                             1
74399                             1
74406                             2
74409                            68
74412                             2
74420                             1
74422                             4
                                  1

10 rows selected.
```

次にプロセス名とバックグラウンド・プロセスの関係を確認します。V$PROCESSビューのPNAME列にはバックグラウンド・プロセス名が格納されます。
Linuxのプロセス名と、PNAME列の値を表にまとめてみました。PMON, PSP0, VKTM, DBW0等は独立したプロセスとして動作していることがわかります。

|OSプロセス名|バックグラウンド・プロセス名|スレッド数|
|:---|:---|---:|
|ora_pmon_{SID}|PMON|1|
|ora_psp0_{SID}|PSP0|1|
|ora_vktm_{SID}|VKTM|1|
|ora_dbw0_{SID}|DBW0|1|
|ora_u002_{SID}|CLMN,SCMN,GEN0,MMAN,DBRM,PMAN,CKPT,SMON,LREG|9|
|ora_gen1_{SID}|GEN1,SCMN|2|
|ora_ofsd_{SID}|OFSD,SCMN|2|
|ora_lgwr_{SID}|LGWR,SCMN,LG00,LG01|4|
|ora_u006_{SID}|多数|67|
	
# DBWRプロセスを増やしてみる
データベース・ライター（DBW）を複数起動するとプロセスがどのように変わるかを確認しました。
下記の例では、データベース・ライターを２つ起動しています。

```
SQL> ALTER SYSTEM SET db_writer_processes = 2 SCOPE=SPFILE;

System altered.

SQL> EXIT

$
$ << 再起動>> 
$
$ ps -ef | grep ora_ | grep -v grep
oracle    82114      1  0 17:59 ?        00:00:00 ora_pmon_O18A
oracle    82116      1  6 17:59 ?        00:00:01 ora_u002_O18A
oracle    82119      1  0 17:59 ?        00:00:00 ora_psp0_O18A
oracle    82123      1  2 17:59 ?        00:00:00 ora_vktm_O18A
oracle    82131      1  0 17:59 ?        00:00:00 ora_gen1_O18A
oracle    82134      1 30 17:59 ?        00:00:05 ora_u006_O18A
oracle    82137      1  0 17:59 ?        00:00:00 ora_ofsd_O18A
oracle    82145      1  0 17:59 ?        00:00:00 ora_dbw0_O18A
oracle    82147      1  0 17:59 ?        00:00:00 ora_dbw1_O18A
oracle    82149      1  0 17:59 ?        00:00:00 ora_lgwr_O18A
$
```

ora_dbw1_O18Aプロセスが起動されていることがわかります。データベース・ライターはあくまで単独プロセスで起動するようです。

# V$SESSIONビューとの関係
V＄SESSIONビューのPROCESS列にはクライアントのプロセスIDが格納されます。バックグラウンド・プロセスのPROCESSID列は、スレッド化されたOracleプロセスはV$PROCESSビューのSPID列とSTID列の結合になります。

```
SQL> SELECT PROCESS FROM V$SESSION WHERE PROGRAM LIKE '%LGWR%';

PROCESS
------------------------
5762_5763

SQL> SELECT SPID, STID FROM V$PROCESS WHERE PNAME='LGWR';

SPID                     STID
------------------------ ------------------------
5762                     5763

```

# 制約

マニュアルには以下の制約が記載されています。
|この初期化パラメータがTRUEに設定された場合、マルチスレッドのOracleモデルが使用可能となり、オペレーティング・システム認証はサポートされません。

インスタンス起動時にパスワード無しで接続してSTARTUPコマンドを実行すると、インスタンスの状態がNOMOUNTからMOUNTに移行する時点でエラーになります。
下記の例ではインスタンス起動を失敗しています。

```
$ sqlplus / as sysdba

SQL*Plus: Release 18.0.0.0.0 - Production on Tue Apr 16 17:40:54 2019
Version 18.3.0.0.0

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

Connected to an idle instance.

SQL> STARTUP
ERROR:
ORA-01017: invalid username/password; logon denied


ORA-01017: invalid username/password; logon denied
SQL> EXIT
$
```

ユーザー名とパスワードを指定して再接続を行い、インスタンスの状態を確認するとSTARTEDとなっており、NOMOUNT状態であることがわかります。ALTER DATABASE文を実行してOPEN状態に遷移しています。

```
$ sqlplus SYS/password as sysdba

SQL*Plus: Release 18.0.0.0.0 - Production on Tue Apr 16 17:42:25 2019
Version 18.3.0.0.0

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


Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.3.0.0.0

SQL> SELECT STATUS FROM V$INSTANCE;

STATUS
------------------------------------
STARTED

SQL> ALTER DATABASE MOUNT;

Database altered.

SQL> ALTER DATABASE OPEN;

Database altered.

```