DB2DBA: DB2 11.1新機能 - ロックエスカレーションを抑止する

DB2 for z/OSには従来からロックエスカレーションを抑止する機能が提供されていたのですが、FIXPACKによる機能追加でDB2 for LUW 11.1.2.2以降でも同様のことが出来るようになりました。

# ロックエスカレーションとは
ロックエスカレーションとは、大量の行ロックを表ロックにまとめることで、ロックの情報を保持するメモリの使用量やロック獲得・解放のオーバーヘッドを削減する機能です。

表を排他的に利用するバッチ処理では処理時間の短縮に有効なケースがありますが、ロック競合が多発し大事故を起こすこともあるため活用するのが難しい機能でもあります。そのため、RDBMSによってはロックエスカレーションの機能は提供されていません（むしろある方が少数派か）。

- ロックエスカレーションあり
    - DB2
    - SQL Server 
- ロックエスカレーションなし
    - Oracle
    - My SQL
    - PostgreSQL

DB2ではロックの情報を保持するメモリ領域であるロックリストが一杯になった場合、もしくはDB構成パラメータ```MAXLOCKS```で指定した割合を超えた場合にロックエスカレーションが発生します。

なお、DB2 9.1以降ではロックリストはセルフチューニングメモリ機能の管理対象となっており、DB構成パラメータ```LOCKLIST```が```AUTOMATIC```の場合は不足時に自動的にサイズ拡張され、従来よりロックエスカレーションが発生しにくくなっています。


# 設定方法
新たに用意されたレジストリ変数```DB2_AVOID_LOCK_ESCALATION```を```ON```にすることで、ロックリストが一杯になった場合はSQL0912Nでエラーが返されるようになります。

```
$ db2set DB2_AVOID_LOCK_ESCALATION=ON -i
```

# 検証してみた
## 環境
- Db2 11.1.3.3 Express-C Edition
- VirtualBox 5.2.3
- Vagrant 2.0.3
- Ubuntu Linux 16.04.4 64-bit (ubuntu/xenial64)

## 検証手順・結果
### ロックリストの縮小
ロックエスカレーションが発生しやすいよう、ロックリストを最小サイズにしておきます。値の単位は4KBです。

```
db2inst1@ubuntu-xenial:~$ db2 update db cfg using locklist 4
DB20000I  The UPDATE DATABASE CONFIGURATION command completed successfully.
db2inst1@ubuntu-xenial:~$ db2 "get db cfg" | grep -i locklist
 Max storage for lock list (4KB)              (LOCKLIST) = 4
```

### SQLの実行（ロックエスカレーション発生ケース）
分離レベルRSで表をスキャンすることで、全レコードのSロックを獲得させてみます。

```
db2 => select count(*) from sysibm.systables with rs

1
-----------
        646

  1 record(s) selected.
```

SQLの実行は成功していますが、その裏ではロックエスカレーションが発生していました。

```
db2inst1@ubuntu-xenial:~$ db2diag -g MESSAGE^=ADM550
2018-04-21-07.57.17.685278+000 E98572E1013           LEVEL: Info
PID     : 611                  TID : 140657632995072 PROC : db2sysc
INSTANCE: db2inst1             NODE : 000            DB   : TESTDB01
APPHDL  : 0-232                APPID: *LOCAL.db2inst1.180421075455
AUTHID  : DB2INST1             HOSTNAME: ubuntu-xenial
EDUID   : 40                   EDUNAME: db2agent (TESTDB01)
FUNCTION: DB2 UDB, data management, sqldEscalateLocks, probe:1
MESSAGE : ADM5501I  The database manager is performing lock escalation. The
          affected application is named "db2bp", and is associated with the
          workload name "SYSDEFAULTUSERWORKLOAD" and application ID
          "*LOCAL.db2inst1.180421075455"  at member "0". The total number of
          locks currently held is "291", and the target number of locks to hold
          is "145". The current statement being executed is "select count(*)
          from sysibm.systables with rs". Reason code: "2"
DATA #1 : Hex integer, 8 bytes
0x830000000004003B

2018-04-21-07.57.17.701216+000 E100154E576           LEVEL: Warning
PID     : 611                  TID : 140657632995072 PROC : db2sysc
INSTANCE: db2inst1             NODE : 000            DB   : TESTDB01
APPHDL  : 0-232                APPID: *LOCAL.db2inst1.180421075455
AUTHID  : DB2INST1             HOSTNAME: ubuntu-xenial
EDUID   : 40                   EDUNAME: db2agent (TESTDB01)
FUNCTION: DB2 UDB, data management, sqldEscalateLocks, probe:3
MESSAGE : ADM5502W  The escalation of "241" locks on table "SYSIBM  .SYSTABLES"
          to lock intent "S" was successful.
```

### DB2_AVOID_LOCK_ESCALATIONの変更
db2setコマンドでレジストリ変数を変更します。

```
db2inst1@ubuntu-xenial:~$ db2set -all
[i] DB2COMM=TCPIP
[i] DB2AUTOSTART=NO
[g] DB2_COMPATIBILITY_VECTOR=MYS
[g] DB2SYSTEM=ubuntu-xenial
db2inst1@ubuntu-xenial:~$ db2set DB2_AVOID_LOCK_ESCALATION=ON -i
db2inst1@ubuntu-xenial:~$ db2set -all
[i] DB2_AVOID_LOCK_ESCALATION=ON
[i] DB2COMM=TCPIP
[i] DB2AUTOSTART=NO
[g] DB2_COMPATIBILITY_VECTOR=MYS
[g] DB2SYSTEM=ubuntu-xenial
```

### SQLの実行（SQL0912Nケース）
ロックエスカレーションを発生させずにSQLを止めることが出来ました。

```
db2 => select count(*) from sysibm.systables with rs

1
-----------
SQL0912N  The maximum number of lock requests has been reached for the
database. Reason code = "1"  SQLSTATE=57011
```

# 参考資料
- IBM Knowledge Center
    - Db2 11.1
        - [DB2_AVOID_LOCK_ESCALATION](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.1.0/com.ibm.db2.luw.admin.regvars.doc/doc/r0005665.html#r0005665__P_DB2_AVOID_LOCK_ESCALATION)
        - [locklist - ロック・リスト用最大ストレージ構成パラメーター](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.1.0/com.ibm.db2.luw.admin.config.doc/doc/r0000267.html)