Oracle 共有サーバ接続関連


## 内容
共有サーバ接続に関する以下の項目を記載。

- 共有サーバ接続の設定
- XMLDB導入時の注意事項


## 共有サーバ接続の設定

### 1. 初期パラメータの確認
以下の初期化パラメータを確認する。  

- SHARED_SERVERSに"1"以上の値が設定されていること。
- DISPATCHERSに正しい値が設定されていること。デフォルト値は"(PROTOCOL=TCP)"。

  
以下のSQLで確認。  
  
```sql:
SQL> col name for a30
SQL> col value for a50
SQL> select name,value from v$parameter where name in ('dispatchers','shared_servers');

 NAME                           VALUE
------------------------------ --------------------------------------------------
dispatchers                    (PROTOCOL=TCP)
shared_servers                 1

```

必要があれば変更。

```sql:
SQL> alter system set shared_servers=5 scope=both;

システムが変更されました。

SQL> alter system set DISPATCHERS='(PROTOCOL=TCP)(DISPATCHERS=5)' scope=both;

システムが変更されました。

SQL> select name,value from v$parameter where name in ('dispatchers','shared_servers');

NAME                           VALUE
------------------------------ --------------------------------------------------
dispatchers                    (PROTOCOL=TCP)(DISPATCHERS=5)
shared_servers                 5

```
  

### 2. 各設定ファイルを確認

- tnsnames.ora
  "(DESCRIPTIN="内に"(SERVER=DEDICATED)"が指定されていないこと。
  → この設定を削除 or "(SERVER=SHARED)"を設定
  
- sqlnet.ora
  "USE_DEDICATED_SERVER=ON"が指定されていないこと。
   → この設定を削除 or "USE_DEDICATED_SERVER=OFF"を設定



### 3. リスナー登録状況を確認
"lsnrctl service"コマンドを実行。ハンドラ"D000〜"が登録されていること。

- 設定の再読み込み
  
```bash:
$ lsnrctl reload
```

- 登録状況確認

```bash:
$ lsnrctl service

LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 25-4月 -2015 21:13:18

Copyright (c) 1991, 2013, Oracle.  All rights reserved.

(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rhel01)(PORT=1521)))に接続中
サービスのサマリー...
サービス"TESTDB01"には、1件のインスタンスがあります。
インスタンス"TESTDB01"、状態READYには、このサービスに対する6件のハンドラがあります...
  ハンドラ:
    "D004" 確立:0 拒否:0 現行:0 最大:1022 状態:ready
       DISPATCHER <machine: rhel01, pid: 5362>
       (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=40818))
    "D003" 確立:0 拒否:0 現行:0 最大:1022 状態:ready
       DISPATCHER <machine: rhel01, pid: 5360>
       (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=45898))
    "D002" 確立:0 拒否:0 現行:0 最大:1022 状態:ready
       DISPATCHER <machine: rhel01, pid: 5358>
       (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=34725))
    "D001" 確立:0 拒否:0 現行:0 最大:1022 状態:ready
       DISPATCHER <machine: rhel01, pid: 5356>
       (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=9412))
    "D000" 確立:0 拒否:0 現行:8 最大:1022 状態:ready
       DISPATCHER <machine: rhel01, pid: 1639>
       (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=55424))
    "DEDICATED" 確立:0 拒否:0 状態:ready
       LOCAL SERVER
コマンドは正常に終了しました。
```

### 4. 共有サーバ接続の確認

V$SESSIONビューのSERVER列で確認する。
SERVER列の内容は以下の通り。

- DEDICATED
    → 専用サーバ接続
- SHARED
    → 共有サーバ接続
- NONE
    → 共有サーバ接続（アイドル状態）


確認方法は以下の通り。

- 接続別セッション数

```sql:
SQL> SELECT SERVER, COUNT(*) FROM V$SESSION GROUP BY SERVER;

SERVER                        COUNT(*)
--------------------------- ----------
DEDICATED                           29
SHARED                               1
NONE                                 1
```

- 現セッションの接続種別

```sql:
SQL> SELECT SERVER FROM V$SESSION WHERE SID = USERENV('SID') ;

SERVER
---------------------------
SHARED
```

- セッションに対応するディスパッチャープロセス（D000〜）

```sql:
SQL> COL PROCESS FOR A20
SQL> COL PROGRAM FOR A40
SQL> COL USERNAME FOR A10
SQL> COL PID FOR A5
SQL> SELECT P.PNAME PNAME, P.SPID PID,S.SID,S.SERIAL#,S.USERNAME,S.PROGRAM PROGRAM
     FROM V$PROCESS P, V$SESSION S
     WHERE P.ADDR = S.PADDR AND P.PNAME LIKE '%D00%';

PNAME           PID          SID    SERIAL# USERNAME   PROGRAM
--------------- ----- ---------- ---------- ---------- ----------------------------------------
D001            5356          44        567 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D002            5358          30         13 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D002            5358          52        575 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D003            5360          39        609 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D003            5360          46         83 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D004            5362          28        859 SYSTEM     sqlplus@rhel01 (TNS V1-V3)
D004            5362          47        571 SYSTEM     sqlplus@rhel01 (TNS V1-V3)

SQL> -- P.SPID列は、"lstener service"で表示されるpidと同じ
SQL> --   DISPATCHER <machine: rhel01, pid: 5358>
SQL> --                                     ~~~~
```


## XMLDB導入時の注意事項

### 内容
XMLDBインストール後、今まで使用していた共有サーバ接続が接続できなくなるという事象が発生。
その時の原因と対応を以下に記載する。

### 事象
XMLDBインストール後、今まで使用していた共有サーバ接続を実施したところ、以下のエラーが発生。

```sql:
$ sqlplus system/oracle@TESTDB01

SQL*Plus: Release 11.2.0.4.0 Production on 土 4月 25 22:17:31 2015

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

ERROR:
ORA-12520: TNS:
リスナーは、リクエストしたサーバー・タイプに使用可能なハンドラを検出できませんで
した。
```


今まで使用していたサービス"TESTDB01"にDISPATCHERがリスナーに登録されていないことを確認。

```bash:
SQL> !lsnrctl service
…（省略）…

サービスのサマリー...
サービス"TESTDB01"には、1件のインスタンスがあります。
  インスタンス"TESTDB01"、状態READYには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "DEDICATED" 確立:0 拒否:0 状態:ready
         LOCAL SERVER
サービス"TESTDB01XDB"には、1件のインスタンスがあります。
  インスタンス"TESTDB01"、状態READYには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "D002" 確立:0 拒否:0 現行:2 最大:1022 状態:ready
         DISPATCHER <machine: rhel01, pid: 5358>
         (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=34725))
コマンドは正常に終了しました。
```

### 原因
XMLDBインストール時に初期化パラメータdispatchersに以下の値を設定したが、この"SERVICE"パラメータの値に不足があったことが原因。
今回は今まで使用していたサービス名が不足していたのが原因。

```sql:
dispatchers="(PROTOCOL=TCP) (SERVICE=<sid>XDB)"
```

以下のように修正する。

```sql:
dispatchers="(PROTOCOL=TCP) (SERVICE=<今まで使用していたサービス名>,<sid>XDB)"
```
   

### 対応

####1. 登録対象サービスの確認
V$SERVICESで、登録をする必要があるサービスを確認。
          
```sql:
SQL> select name from v$services;

NAME
------------------------------
TESTDB01XDB
TESTDB01
SYS$BACKGROUND
SYS$USERS

-- SYS$USERS
-- → ユーザーセッションを明示的に識別するサービス名なしに
--    確立したとき使用するデフォルトのサービス名。
-- SYS$BACKGROUND
-- → すべてのOracle Databaseのバックグラウンドプロセスで構成。
```


####2. 初期化パラメータの変更
  
```sql:
SQL> alter system set dispatchers='(PROTOCOL=TCP)(SERVICE=TESTDB01,TESTDB01XDB)' scope=both;

システムが変更されました。

SQL> select name,value from v$parameter where name = 'dispatchers';

NAME                           VALUE
------------------------------ --------------------------------------------------
dispatchers                    (PROTOCOL=TCP)(SERVICE=TESTDB01,TESTDB01XDB)
```


####3. リスナーの再読み込み

```bash:
SQL> !lsnrctl reload
…（省略）…

SQL> !lsnrctl service
…（省略）…

サービスのサマリー...
サービス"TESTDB01"には、1件のインスタンスがあります。
  インスタンス"TESTDB01"、状態READYには、このサービスに対する2件のハンドラがあります...
    ハンドラ:
      "D002" 確立:0 拒否:0 現行:1 最大:1022 状態:ready
         DISPATCHER <machine: rhel01, pid: 5358>
         (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=34725))
      "DEDICATED" 確立:0 拒否:0 状態:ready
         LOCAL SERVER
サービス"TESTDB01XDB"には、1件のインスタンスがあります。
  インスタンス"TESTDB01"、状態READYには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "D002" 確立:0 拒否:0 現行:1 最大:1022 状態:ready
         DISPATCHER <machine: rhel01, pid: 5358>
         (ADDRESS=(PROTOCOL=tcp)(HOST=rhel01)(PORT=34725))
コマンドは正常に終了しました。

```

####4. 接続確認
sqlplusを8つ立ち上げ、4つを"TESTDB01"サービスに、残りを"TESTDB01XDB"サービスに共有サーバで接続。
以下のSQLで接続状況を確認。
 
```sql:
SQL> COL SERVICE_NAME FOR A20
SQL> SELECT SERVICE_NAME,SERVER,COUNT(*) 
     FROM V$SESSION GROUP BY SERVICE_NAME,SERVER
     ORDER BY 1,2;

SERVICE_NAME         SERVER                        COUNT(*)
-------------------- --------------------------- ----------
SYS$BACKGROUND       DEDICATED                           26
TESTDB01             NONE                                 3
TESTDB01             SHARED                               1
TESTDB01XDB          NONE                                 4
```