環境
- SpringBoot 3.1
- PostgreSQL 16
問題の概要
CSVを読み込んでDBに登録する、という処理を実装したのですがCSVが数十万件とかなり膨大だったのでシングルスレッドでは時間がかかり過ぎました。
そのためマルチで動かそうと思いlist.parallelStream()でインサート処理を書き、呼び出し元のメソッドに@Transactionalを付与しました。
それで確認のために一発どでかいCSVを使用して@Transactionalがちゃんと効いているか確認したところ、めちゃめちゃコミットされてました。
@Transactionalはpublicメソッドに書かないとだめだとかなんだとか色々制約があるのでそれかなと思ったけど特に原因となりそうなところが見当たらなかったです。(結局はこの色々な制約の中の1つに引っかかっているはず)
それでうーんと悩んで何となくlist.parallelStream()からlist.stream()に変えてやってみたらちゃんと処理が完了してからコミットされてました。
ちゃんと原因究明はしていないし、parallelStream()でも@Transactionalを効かせる方法はあるのだろうけど@Transactionalを書いたらparallelStream()内、というか複数スレッドでDB操作はしない方が無難かなと思いました。
ということで頑張ってシングルスレッドで動かします。
追記
恐らく以下がparallelStreamで@Transactionalが効かない理由です。
Javadocに書いてありました。
https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html
トランザクション管理
このアノテーションは通常、
PlatformTransactionManager
によって管理されるスレッドバインドトランザクションで機能し、トランザクションを現在の実行スレッド内のすべてのデータアクセス操作に公開します。注: これは、メソッド内で新しく開始されたスレッドには伝播されません。
コメント