DB2の環境構築手順をコマンド単位で丁寧に書いてみる

## 概要
業務の中で検証用途のDB2環境構築を行う機会がありました。
「postgresは構築したことあるし、そんなに苦労しないよね～？」と思っていたのですがやってみると想像以上にハマったので、同じ悩みを抱えている人のために書き残してみたいと思います。

## 環境情報
AWSのEC2上にDBサーバを構築します。

* サーバ
  * OS：WindowsServer2016
  * DB2バージョン：DB2 v11.1.3030.239
  * DB2ライセンス：IBM Db2 - 90日間評価版
* クライアント
  * OS：Windows7

## 作業項目
* DB2インストール
* インスタンス作成
* データベース作成
* 表スペース作成
* リモート接続設定

## 要件
* 命名規則
    * インスタンス名：INSTNM
    * データベース名：DBNM
    * 表スペース：TABLENM
* データベース作成時のパラメータ
    * USING CODESET：IBM-943
    * TERRITORY: JP
    * COLLATE USING: IDENTITY 
    * PAGESIZE: 16384

## DB2のインストール
公式サイトからインストーラをダウンロードし、起動します。

* https://www.ibm.com/analytics/jp/ja/technology/db2/db2-trials.html

特に指定が無ければインストーラに従ってデフォルト値で進めて問題ないと思います。
ここでは`db2admin`ユーザのパスワードを`password1234`とします。

## DB2 コマンド・ウィンドウの起動
DB2の操作は`DB2 コマンド・ウィンドウ`というCLIを用いて行います。
`DB2 コマンド・ウィンドウは`DB2インストールの際、一緒にインストールされています。
`スタート`>`IBM DB2 DB2COPY1（デフォルト）`>`DB2 コマンド・ウィンドウ`から起動しましょう。

## デフォルトインスタンスの削除

一つの問題点として、インストール時に`DB2`という名前（固定）のデフォルトインスタンスが自動的に作成されます。[^1]
今回の要件には不要ですし、余分なインスタンスが残っているのもよろしくないので削除しておきます。

[^1]: インストール時に名前変更もしくは作成要否の選択ができればよいのですが、どうやら無理なようでした。

### 確認
```:db2cmd.exe
$ db2ilist
DB2
```

### インスタンス停止

```:db2cmd.exe
$ db2stop
SQL1064N  DB2STOP の処理が正常に終了しました。
```

### インスタンス削除

```:db2cmd.exe
$ db2idrop DB2
DB20000I  DB2IDROP コマンドが正常に完了しました。
```

### 確認

```:db2cmd.exe
$ db2ilist

```

## インスタンス作成
`DB2`インスタンスが削除できたら、`db2icrt`コマンドでインスタンスを作成します。

### 作成
```:db2cmd.exe
$ db2icrt -U db2admin,password1234 -p C:\ INSTNM
```
### 確認

```:db2cmd.exe
$ db2ilist

INSTNM

```

これでインスタンス作成は完了です。

## データベース作成

続いてデータベースを作成します。

### インスタンス切り替え&起動
操作対象のインスタンスはOSの`DB2INSTANCE`環境変数によって切り替えることができます。
デフォルトだと`DB2`となっているので、先ほど作成したインスタンス（`INSTNM`）に変更してあげましょう。
今どのインスタンスを操作しているかは、`db2 get instance`コマンドで確認することができます。

```:db2cmd.exe
$ set DB2INSTANCE=INSTNM

$ db2 get instance

 現在のデータベース・マネージャー・インスタンスは INSTNM    です。

```

### 作成
SQLで`CREATE DB`を実行し、データベースを作成します。
コマンドが正常終了するまで少し時間がかかります。

```:db2cmd.exe

$ db2 "CREATE DB DBNM ON C:\INSTNM DBPATH ON C: ALIAS DBNM USING CODESET IBM-943 TERRITORY JP COLLATE USING IDENTITY PAGESIZE 16384"

DB20000I  CREATE DATABASE コマンドが正常に完了しました。

```

### 確認

```:db2cmd.exe
$ db2 LIST DB DIRECTORY

 システム・データベース・ディレクトリー

 ディレクトリー中の項目数 = 1

データベース 1 項目:

 データベース別名                     = DBNM
 データベース名                             = DBNM
 ローカル・データベース・ディレクトリー = C:
 データベース・リリース・レベル       = 14.00
 コメント                             =
 ディレクトリー項目タイプ             = 間接
 カタログ・データベース・パーティション番号 = 0
 代替サーバー・ホスト名               =
 代替サーバーのポート番号             =

```

### 接続

```:db2cmd.exe

$ db2 CONNECT TO DBNM USER db2admin USING password1234

   データベース接続情報

 データベース・サーバー = DB2/NT64 11.1.3.3
 SQL 許可 ID            = DB2ADMIN
 ローカル・データベース別名 = DBNM

```

これでデータベース作成は完了です。

## 表スペース作成
データベースに接続した状態で、表スペースを作成していきます。

### 作成
SQLで`CREATE TABLESPACE`コマンドを実行し、表スペースを作成します。

```:db2cmd.exe
$ db2 "CREATE TABLESPACE TABLENM MANAGED BY DATABASE USING (FILE'C:\INSTNM\INSTNM\NODE0000\DBNM\TABLENM\tablenm.db2' 10000) EXTENTSIZE 16 PREFETCHSIZE 32"

DB20000I  SQL コマンドが正常に完了しました。

```

### 確認

```:db2cmd.exe
db2 "LIST TABLESPACES"

           現在のデータベースの表スペース

 表スペース ID                        = 0
 名前                                 = SYSCATSPACE
 タイプ                               = データベース管理スペース
 内容                                 = すべての永続データ。 REGULAR 表スペース。
 状態                                 = 0x0000
   詳しい説明:
     正常

 表スペース ID                        = 1
 名前                                 = TEMPSPACE1
 タイプ                               = システム管理スペース
 内容                                 = システム一時データ
 状態                                 = 0x0000
   詳しい説明:
     正常

 表スペース ID                        = 2
 名前                                 = USERSPACE1
 タイプ                               = データベース管理スペース
 内容                                 = すべての永続データ。 LARGE 表スペース。
 状態                                 = 0x0000
   詳しい説明:
     正常

 表スペース ID                        = 3
 名前                                 = SYSTOOLSPACE
 タイプ                               = データベース管理スペース
 内容                                 = すべての永続データ。 LARGE 表スペース。
 状態                                 = 0x0000
   詳しい説明:
     正常

 表スペース ID                        = 4
 名前                                 = TABLENM
 タイプ                               = データベース管理スペース
 内容                                 = すべての永続データ。 LARGE 表スペース。
 状態                                 = 0x0000
   詳しい説明:
     正常

```

これで表スペースの作成は完了です。

## リモート接続設定（サーバ側）
都度サーバにログインして操作するならこれで完了なのですが、さすがにリモートで操作したいですよね。
そこで「よっしゃこれで接続や～」と思って`CONNECT TO`すると普通に弾かれます。
リモート接続できるようにはサーバとクライアント両方に設定が必要なのです。やっていきましょう。

### リモート接続設定

```:db2cmd.exe
// 設定

$ db2set DB2COMM=TCPIP

$ db2 update dbm cfg using svcename 50000

DB20000I  UPDATE DATABASE MANAGER CONFIGURATION コマンドが正常に完了しました。
SQL1362W  即時変更のためにサブミットされた 1
つ以上のパラメーターが動的に変更されませんでした。
クライアントの変更は、次回のアプリケーション始動時、または TERMINATE
コマンドが発行されるまで有効になりません。 次の DB2START
コマンドまで、サーバーの変更は有効になりません。


// 再起動

$ db2 connect reset

$ db2stop

$ db2start

```

### 確認

```:db2cmd.exe
netstat -nao | grep 50000

  TCP    0.0.0.0:50000          0.0.0.0:0              LISTENING       9424
  TCP    [::]:50000             [::]:0                 LISTENING       9424

```
50000番ポートが`LISTENING`になってればサーバ側の設定は完了です。

また上記手順に加えて、

* OSのファイアウォール
* AWSのセキュリティグループ（AWS上で構築した場合）

で50000番ポートのインバウンド通信を許可する必要がありますが、本記事の趣旨から若干外れるので説明は省略します。[^2]

[^2]: 需要がもしあれば追記します。

## リモート接続設定（クライアント側）

### リモートノードの登録
SQLで`CATALOG TCPIP NODE`コマンドを実行し、リモートノードを登録します。

```:db2cmd.exe
$ db2 "CATALOG TCPIP NODE DB2NODE1 REMOTE 10.0.0.1 SERVER 50000"

DB20000I  CATALOG TCPIP NODE コマンドが正常に完了しました。
DB21056W  ディレクトリーの変更は、ディレクトリー・キャッシュがリフレッシュされる
まで反映されません。

```

* DB2NODE1・・・ノード名（任意の名前）
* 10.0.0.1・・・DB2サーバのIP
* 50000・・・ポート

### リモートデータベースの登録
SQLで`CATALOG DB`コマンドを実行し、リモートデータベースを登録します。

```:db2cmd.exe
$ db2 "CATALOG DB DBNM AT NODE DB2NODE1"

DB20000I  CATALOG DATABASE コマンドが正常に完了しました。
DB21056W  ディレクトリーの変更は、ディレクトリー・キャッシュがリフレッシュされる
まで反映されません。

```

* DBNM・・・データベース名
* DB2NODE1・・・上記で登録したノード名

### 接続

```:db2cmd.exe
$ db2 "CONNECT TO DBNM USER db2admin USING password1234"

   データベース接続情報

 データベース・サーバー = DB2/NT64 11.1.3.3
 SQL 許可 ID            = DB2ADMIN
 ローカル・データベース別名 = DBNM

```

これで接続設定は完了です。

## 最後に
* Dockerイメージあるので、検証用途であればこれでサクッとやっちゃうのも有りですね。  
https://hub.docker.com/r/ibmcom/db2