2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring Data JPAのMySQL接続周りについて

Last updated at Posted at 2017-11-10

概要

SpringDataJPAを使用していた際に疑問となった、DB接続周りについて調査した。

環境

Java 8
SpringBoot 1.5.7.RELEASE

コネクションの調査

DBに接続するアプリケーションを起動すると、コネクションが10本自動で張られていた。
アプリケーションを立ち上げる際にDBが落ちていると起動が失敗するのでなるほどなあという感じ。
(一番上のコネクションは確認用に接続しているもの)

コネクションが10本自動で張られるのは、使用されているDBコネクションプーリングの初期値initialSizeによるのではと思います。

tomokaneさんよりコメントいただきました。
今回のケースだと、spring.datasource.tomcat.initial-sizeの値を変えると起動時のコネクション数が変わりました。

mysql> show processlist;
+-----+------+------------------+---------+---------+------+----------+------------------+
| Id  | User | Host             | db      | Command | Time | State    | Info             |
+-----+------+------------------+---------+---------+------+----------+------------------+
|   3 | user | localhost        | test_db | Query   |    0 | starting | show processlist |
| 108 | user | 172.19.0.1:45338 | test_db | Sleep   |   22 |          | NULL             |
| 109 | user | 172.19.0.1:45340 | test_db | Sleep   |   22 |          | NULL             |
| 110 | user | 172.19.0.1:45342 | test_db | Sleep   |   22 |          | NULL             |
| 111 | user | 172.19.0.1:45344 | test_db | Sleep   |   22 |          | NULL             |
| 112 | user | 172.19.0.1:45346 | test_db | Sleep   |   21 |          | NULL             |
| 113 | user | 172.19.0.1:45348 | test_db | Sleep   |   21 |          | NULL             |
| 114 | user | 172.19.0.1:45350 | test_db | Sleep   |   21 |          | NULL             |
| 115 | user | 172.19.0.1:45352 | test_db | Sleep   |   21 |          | NULL             |
| 116 | user | 172.19.0.1:45354 | test_db | Sleep   |   21 |          | NULL             |
| 117 | user | 172.19.0.1:45356 | test_db | Sleep   |   21 |          | NULL             |
+-----+--------+------------------+----------------+---------+------+----------+------------------+

また同時に10を超えるアクセスを立ち上げたアプリケーション経由でしたところ、コネクションが増えたり全て使われている様子はなかった。
どのようにコントロールされているかまでは未調査。

トランザクションの調査

トランザクションをするためには、トランザクションの範囲にしたいメソッドに対して「@Transactional」アノテーションを付与する。

@Transactional
public void methodName() {
    // SELECT文その1
    doSelect1();
  
    // 10秒スリープ
    try{
        Thread.sleep(10000);
    } catch(Exception e) {
    }
  
    // SELECT文その2
    doSelect2();
}

確認のため、上記のようなメソッドを作成した。
スリープの間にSELECT文その2の対象となるレコードを挿入してもSELECT結果には含まれていなかった。

タイムアウトについて

application.propertiesにて値を設定できる。

// 20秒
spring.transaction.default-timeout=20 

個別の設定はアノテーションで行う。

// 10秒
@Transactional(timeout = 10)

DB側でもタイムアウトが設定しており、MySQLだと以下のようになっていた。
innodb_lock_wait_timeoutがその値で、初期値が50秒となる。

mysql> show global variables like '%wait%';
+---------------------------------------------------+----------+
| Variable_name                                     | Value    |
+---------------------------------------------------+----------+
| innodb_lock_wait_timeout                          | 50       |
| innodb_spin_wait_delay                            | 6        |
| lock_wait_timeout                                 | 31536000 |
| performance_schema_events_waits_history_long_size | 10000    |
| performance_schema_events_waits_history_size      | 10       |
| wait_timeout                                      | 28800    |
+---------------------------------------------------+----------+

挙動を確認するため、行ロックをかけたレコードに対してJpaRepositoryのsaveメソッドを実行した。
行ロックは下記の用にあらかじめmysqlサーバに入って行っておく。

mysql> start transaction;                                                                                                                                                                                 Query OK, 0 rows affected (0.01 sec)
 
mysql> update test_db column1 = 'hoge' WHERE column2 = '0';                                                                                                               Query OK, 0 rows affected (0.00 sec)
Rows matched: 2  Changed: 0  Warnings: 0

この行ロックに引っかかるようsaveメソッドを実行したところ、設定値の時間後に上記exceptionが投げられるのを確認した。
(ちなみにログを見る限り、saveメソッドの内部ではSELECT→UPDATEが行われている様子)

org.springframework.dao.CannotAcquireLockException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement
2
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?