2
1

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.

[Java]トランザクションをネストした場合に必要なコネクションの数

Last updated at Posted at 2018-08-14

トランザクションのネスト数=必要なコネクション数だっけ???

マルチスレッドなバッチ処理のコネクションプールのプールサイズを見積もった際、トランザクションのネストが発生するので 当然ネストする分のコネクションも必要 ということで、スレッド数 × トランザクションのネスト数 でプールサイズを設定しました。

あとになって、「ほんとにそう(ネスト分も必要)だっけ?」と自分の中の 当たり前 に漠然とした不安を覚え、ググってみても そのものズバリの回答にたどり着けなかった ので、サンプルコードを組んで確認することにしました。

結論

いきなり身も蓋もないですが、
 トランザクションのネスト数=必要なコネクション数
でした。

ということで、結果だけを知りたかった場合は、以下はスルーして構いません。

検証環境

  • Oracle JDK 8 u161
  • spring-boot 1.4.3
  • Tomcat JDBC Connection Pool 8.5.6

サンプルコード(抜粋)

application.properties
# ConnectionPool
spring.datasource.tomcat.maxActive=1
spring.datasource.tomcat.maxIdle=1
spring.datasource.tomcat.minIdle=0
spring.datasource.tomcat.initialSize=0
App.java
@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(App.class, args);
        Main bean = context.getBean(Main.class);
        bean.doNestedTransaction();
    }

}
Main.java
@Component
public class Main {

    @Autowired
    private MainTarnsaction mainTransaction;

    public void doNestedTransaction() {
        mainTransaction.beginTransaction();
    }

}
MainTarnsaction.java
@Component
public class MainTarnsaction {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private NestedTransaction nestedTransaction;

    @Transactional
    public void beginTransaction() {
        jdbcTemplate.execute("update Hoge set val = 'aaa' where id = '1'");
        nestedTransaction.beginTransaction();
    }

}
NestedTransaction.java
@Component
public class NestedTarnsaction {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void beginTransaction() {
        jdbcTemplate.execute("update Hoge set val = 'bbb' where id = '2'");
    }

}

実行結果

(1) プールサイズを 1spring.datasource.tomcat.maxActive=1)に設定して実行した場合

org.springframework.transaction.CannnotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is org.apache.tomcat.jdbc.pool.PoolExhaustedException: [main] Timeout: Pool empty. Unable to fetch a connection in 30 seconds. none available[size:1; busy:1; idel:0; lastwait:30000].
...
at xxx.NestedTransaction$$EnhancerBySpringCGLib$$xxx.beginTransaction(<generated>)
...
at xxx.MainTransaction$$EnhancerBySpringCGLib$$xxx.beginTransaction(<generated>)
at xxx.Main.doNestedTransaction(Main.java:xx)
...

上記の通り、ネスト側のトランザクションのためのコネクションをプールから割り当ることができず、例外が発生しました。

(2) プールサイズを 2spring.datasource.tomcat.maxActive=2)に設定して実行した場合

(予想通りですが)正常終了しました。

おわりに

自分の中のモヤモヤはこれでスッキリしました。
同じ疑問にぶつかった人の参考になれば幸いです。

2
1
0

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?