tamuraです。

最近、CL-DBIでデータベースをコネコネしていたのですが、本格的なWebアプリを作ろうとしたらコネクションプールが必要なのではないかと思い、コネクションプールを作りました。

https://github.com/tamurashingo/cl-dbi-connection-pool


コネクションプーリングとは、データベースにアクセスする時、アクセスのたびに接続(コネクション)を確立するのではなく、あらかじめ一定数のコネクションを確立しておき、それを使い回す手法。データベースアクセスの負荷を減らすために用いられる。
http://e-words.jp/w/%E3%82%B3%E3%83%8D%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0.html


基本

CL-DBI でできることはほぼできるように作っています。

接続

オプションは CL-DBI と同じです。 独自オプションとして初期の接続数と最大接続数が指定できます。

基本パラメータ

:driver-name
データベースドライバ
:sqlite3
:mysql
:postgres
:database-name
接続先データベース名
:username
接続用ユーザ名
:password
接続用パスワード
:initial-size
初期のデータベース接続数
:max-size
最大データベース接続数

CL-USER> (defparameter *connection-pool*
                       (dbi-cp:make-dbi-connection-pool :mysql
                                                        :database-name "dbi-cp"
                                                        :username "root"
                                                        :password "password"
                                                        :initial-size 1
                                                        :max-size 3))
*CONNECTION-POOL*

コネクションの取得

get-connection でコネクションプールから取得します。

CL-USER> (defparameter *conn* (dbi-cp:get-connection *connection-pool*))
*CONN*

コネクションが取得できない場合は、 <dbi-cp-no-conection> が発生します。

;; 2つめ
CL-USER> (dbi-cp:get-connection *connection-pool*)
#<DBI-CP.PROXY:<DBI-CONNECTION-PROXY> {1004ED7CD3}>
;; 3つめ
CL-USER> (dbi-cp:get-connection *connection-pool*)
#<DBI-CP.PROXY:<DBI-CONNECTION-PROXY> {1004ED7DE3}>
;; 4つめは取得できないためエラー
CL-USER> (handler-case (dbi-cp:get-connection *connection-pool*)
           (error (e) e))
#<DBI-CP.ERROR:<DBI-CP-NO-CONNECTION> {1005118183}>

Prepare, Execute, Fetch

ここらへんはCL-DBIと同じです。

CL-USER> (let* ((query (dbi-cp:prepare *conn* "SELECT * FROM person where id = ?"))
                (result (dbi-cp:execute query 1)))
           (dbi-cp:fetch result))
(:|id| 1 :|name| "tamura")

do-sqlも同じです。

コネクションの返却

disconnect でコネクションを返却します。

CL-USER> (dbi-cp:disconnect *conn*)
NIL

内部では begin-transaction していたら rollback しています。 do-sqlstart transaction とか打たれたら困ります。

データベースからの切断

shutdown ですべてのコネクションを切断します。

CL-USER> (dbi-cp:shutdown *connection-pool*)
NIL

今後について

Javaなどのコネクションプールにある機能が今はないので、以下のような機能を作っていきたいです。

接続チェック

1~10分に1回、 select 1 みたいなSQLを発行して、接続が切れないようにする機能。

返却漏れの検出

最後に使ってからしばらく操作がないコネクションを検出したい。