As I understand it, all transactions are connected by a thread (i.e., with the context stored in ThreadLocal). For example, if:
- I start a transaction in a transactional parent method
- Make database insert # 1 into an asynchronous call
- Make database insert # 2 into another asynchronous call
This will then lead to two different transactions (one for each insertion), even if they share the same "transactional" parent.
For example, suppose I perform two inserts (and using a very simple example, i.e. not using an executor or a terminating future for brevity, etc.):
@Transactional public void addInTransactionWithAnnotation() { addNewRow(); addNewRow(); }
Performs both inserts, if required, as part of the same transaction.
However, if I wanted to parallelize these inserts for performance:
@Transactional public void addInTransactionWithAnnotation() { new Thread(this::addNewRow).start(); new Thread(this::addNewRow).start(); }
Then, each of these generated threads will not participate in the transaction at all, since the transactions are flow-related.
Key Question : Is there a way to safely propagate a transaction to child threads?
The only solutions that I decided to solve this problem:
- Use a JTA or some XA manager, which by definition should be capable of this. However, I ideally do not want to use XA for my solution because of this overhead
- Combine all the transactional work that I want to do (in the above example, the
addNewRow() function) into one thread and do all the previous work in multithreaded mode. - Define how InheritableThreadLocal is used in transaction status and distribute it to child threads. I am not sure how to do this.
Are there any other solutions? Even if it looks a bit like a workaround (like my solutions above)?
source share