[Scala]Play framework2.0.1でMySQLに繋いだ時に、コネクションがタイムアウトする

2012年6月6日

MySQLに接続するように設定したPlay frameworkのアプリケーションで

[error] c.j.b.ConnectionHandle - Database access problem. Killing off all remaining connections in the connection pool. SQL State = 08S01
[error] application -

! @6ai2nh1a8 - Internal server error, for request [GET /salons?page=2] ->

play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[SQLException: Timed out waiting for a free available connection.]]
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1.jar:2.0.1]
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1.jar:2.0.1]
    at akka.actor.Actor$class.apply(Actor.scala:311) [akka-actor.jar:2.0.1]
    at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1.jar:2.0.1]
    at akka.actor.ActorCell.invoke(ActorCell.scala:619) [akka-actor.jar:2.0.1]
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:196) [akka-actor.jar:2.0.1]
Caused by: java.sql.SQLException: Timed out waiting for a free available connection.
    at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:503) ~[bonecp.jar:0.7.1.RELEASE]
    at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:114) ~[bonecp.jar:0.7.1.RELEASE]
    at play.api.db.DBApi$class.getConnection(DB.scala:62) ~[play_2.9.1.jar:2.0.1]
    at play.api.db.BoneCPApi.getConnection(DB.scala:264) ~[play_2.9.1.jar:2.0.1]
    at play.api.db.DBApi$class.withConnection(DB.scala:75) ~[play_2.9.1.jar:2.0.1]
    at play.api.db.BoneCPApi.withConnection(DB.scala:264) ~[play_2.9.1.jar:2.0.1]

というようなエラーが出る事がある。

これは、MySQLのコネクションがタイムアウトで切断された時に、接続が無いよ!というエラーメッセージです。

MySQLでは、タイムアウトの時間を長くする、というような対処方法がありますがタイムアウトを無効にするという設定がありません。

なので、アプリケーションで接続をキープする設定をしてみます。

#play.api.db.DBApi.scala
のソースを読んでみますと、

データソースに対して「setConnectionTestStatement」を実行しています。

conf.getString("connectionTestStatement").map(datasource.setConnectionTestStatement(_))

この「setConnectionTestStatement」接続をテストするために使用するコマンドを指定するのですが

Play frameworkで新規プロジェクトで作った場合にはapplication.confには設定項目がありません。

なので、以下のように指定します。

db.default.connectionTestStatement = "select 1;"

これはMySQLで一番負荷が小さくて発行できるコマンドとしてselect 1;を使っています。

これで、決まった時間で定期的に「select 1;」をMySQLに発行してくれるようになります。

未分類

Posted by GENDOSU