ActiveRecordのestablish_connectionに気をつけろ

Rails3.1.3の話。

別DBにつなぐときの、ActiveRecordのestablish_connectionに気をつけろ。やつは1クラスごとに独自にdatabase.ymlのpool設定分のコネクションプールを作るぞッ。プールの意味ない!!

マスターDB1台で運用しているときは全然問題ない。コネクションプールは大変賢く働いてくれる。だが、2台目を運用し始めたとき、安易にestablish_connectionでつなぐと簡単に too many connections で、落ちる。

たとえば、ワーカー10個で、establish_connectionで別DB「hoge_db」に接続することにしたクラスが10個あったとしよう。その別DBへの接続設定(database.yml)で 「pool: 5」 としたとしよう。

そしてワーカーを立ち上げたとき、hoge_dbへのコネクション数はみるみるふくれあがり、ワーカー数(10)×establish_connection利用のクラス数(10)×pool設定数(5)で、実に500 100個のコネクションを張るぞ!

対応策としては、下記の4とおりが考えられる。

A、別DBのdatabase.yml設定はpoolを1に設定する。
(急場しのぎ。応急処置レベル。ちなみに0にはできないらしい)
B、コネクションプールをやめる
【参考】http://d.hatena.ne.jp/hxmasaki/20100812/1281588958
C、別DBへのコネクションプールを引き受けるクラスを作って継承する。
【参考】http://d.hatena.ne.jp/rudeboyjet/20101221/p1
D、適宜Rails.configuration.database_configuration の設定を変えて運用してみる。
【参考】http://yaplog.jp/gmodev/archive/71

いま、急場しのぎでAの対応をしている。根本解決として有望なのは、CかDかなぁと思う。どちらにしてもよく検証しないとなぁ。

Bは、ケースによってはアリだけど、僕のケースでは採用できないかな、と。

どっかに落ちてないのかな、解決済みのアイテムが。。。

【追記:2012/4/30】
Dの解決方法は、結局 establish_connection してるので、今回の地獄を解決してくれない。ので、Cの方法がたった一つの冴えたやり方っぽい。
【追記:2012/5/29】
コネクションはワーカー内でスレッドとか使って並列DBアクセスとかしない限りpool値分の接続を作ったりとかはしない模様。