Spring の DataSource に DBCP を使用する

公開日: : 最終更新日:2014/01/26 SpringFramework , ,

Spring の DataSource に DBCP を設定してみたのでメモしておきます。

icatch-dbcp-219581864

目次

1. 背景

Spring を使った Web アプリをリリースしたのですが、定期的にデータベースからの応答がなくなるというご連絡をいただき、サーバを調査したところデータベースのコネクションに問題があることがわかりました。

原因は、コネクションがプールされておらず、大量のデータを受け取ると応答がなくなるというもの何ともアレなものでした。。。

2. 動作環境

動作環境は次の通りです。まずは Java のバージョン。

$ java -version
java version "1.7.0_11"
Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)

Spring と DBCP のバージョンは次の通りです。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>3.0.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>

3. applicationContext.xml を見直す

applicationContext.xml を見直すと、 DataSource の class は次のものになっていました。

  • org.springframework.jdbc.datasource.DriverManagerDataSource

この org.springframework.jdbc.datasource.DriverManagerDataSource ですが、JavaDoc を見ると次のように書いてありました。

NOTE: This class is not an actual connection pool; it does not actually pool Connections.

Useful for test or standalone environments outside of a J2EE container,

If you need a “real” connection pool outside of a J2EE container, consider Apache’s Jakarta Commons DBCP or C3P0.

コネクションはプールしないしテスト用、コネクションプールしたいなら DBCP や C3P0 を使えとありました。

まさにこれが原因です。DataSource に設定する class は何の疑いもなく DriverManagerDataSource を使っていましたが、これはテスト用だったんですね。。。

4. DataSource に DBCP を使う

“spring datasource dbcp” で検索すると Spring や MySQL のサイトにヒット。

設定例も書いてありました。

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${db.driver}"/>
    <property name="url" value="${db.jdbcurl}"/>
    <property name="username" value="${db.username}"/>
    <property name="password" value="${db.password}"/>
    <property name="initialSize" value="3"/>
</bean>

5. DBCP 適用前後での比較

コネクション数の比較を残しておいたのでメモしておきます。

5-1. 適用前:

show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 6     |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 1     |
+-------------------+-------+
1 row in set (0.00 sec)
show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 28    |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 1     |
+-------------------+-------+
1 row in set (0.00 sec)
show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 76    |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 1     |
+-------------------+-------+
1 row in set (0.00 sec)

Connections の値がどんどん増えていきますが、Threads_connected の値は常に 1 のままです。
コネクションがプールされておらず、次々に生成されているものと思われます。

5-2. 適用後:

show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 13    |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 9     |
+-------------------+-------+
1 row in set (0.00 sec)
show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 13    |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 9     |
+-------------------+-------+
1 row in set (0.00 sec)
show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 13    |
+-----------------------------------+-------+
7 rows in set (0.00 sec)

show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 9     |
+-------------------+-------+
1 row in set (0.00 sec)

何度もクエリを投げても、Connections, Threads_connected ともに値は一定です。
コネクションがプールされているものと思われます。

6. まとめ

DriverManagerDataSource がテスト用だったとは知りませんでした。

とんだ恥をかいてしまいましたが、でもおかげで絶対に次に活かせる経験になりました。

7. その他の Spring に関する記事

Spring に関する記事は次の通りです。
気になる記事があったらぜひチェックしてみてください!

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

icatch-log_5578829409

SpringJDBC が発行する SQL をログに出力する

SpringJDBC が発行する SQL を確認する必要があったので Apache log4j 1.

記事を読む

icatch-spring

spring framework を使ったデスクトップアプリ(standalone app)で context から getBean でオブジェクトを取得する

Java では珍しく Web ではなくデスクトップアプリの開発があり、そのプロジェクトで Sprin

記事を読む

icatch-java

Spring の設定ファイル applicationContext.xml の内容をプロパティファイルに切り出す

Spring の設定ファイルである applicationContext.xml に DataSou

記事を読む

icatch-mysql_5578829409

MySQL の JDBC ドライバで設定しておきたい rewriteBatchedStatements プロパティ

データベースに MySQL を使った Java アプリのバッチ更新処理について非常に勉強になることが

記事を読む

icatch-cron_5578829409

Spring の Scheduled アノテーションを使った cron サンプル

Spring の @Scheduled アノテーションを使った cron サンプルプログラムを作成し

記事を読む

Financial injection

spring framework を使ったデスクトップアプリ(standalone app)で context から getBean でオブジェクトを取得する。@Autowired による紐付け

先日 spring framework を使ったデスクトップアプリ(standalone app)で

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


× 一 = 5

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑