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-sql
で start transaction
とか打たれたら困ります。
データベースからの切断
shutdown
ですべてのコネクションを切断します。
例
CL-USER> (dbi-cp:shutdown *connection-pool*)
NIL
今後について
Javaなどのコネクションプールにある機能が今はないので、以下のような機能を作っていきたいです。
接続チェック
1~10分に1回、 select 1
みたいなSQLを発行して、接続が切れないようにする機能。
返却漏れの検出
最後に使ってからしばらく操作がないコネクションを検出したい。