spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.
https://spring.io/projects/spring-data
Apache License 2.0
776 stars 674 forks source link

Deprecate ChainedTransactionManager [DATACMNS-1817] #2232

Closed spring-projects-issues closed 3 years ago

spring-projects-issues commented 4 years ago

Mark Paluch opened DATACMNS-1817 and commented

ChainedTransactionManager is the primary class in org.springframework.data.transaction that is used for multi-transactionmanager arrangements. It is useful to coordinate transactions across multiple resources especially when one transaction manager is a Spring one and the other is a foreign one.

Over time, we found that we're basically emulating distributed transactions on a best-effort basis with known gaps. These gaps lead to inconsistencies or unexpected behavior during rollbacks. Part of the problem is that resource/synchronization storage is a singleton ThreadLocal. Using two transaction managers based on AbstractPlatformTransactionManager causes the first transaction manager to handle all synchronizations regardless of their resource origin (primary and secondary transactional resources). If the second transaction manager commit fails, then already all synchronizations are processed and there's no way to recover.

Therefore, we're going to deprecate ChainedTransactionManager and the entire org.springframework.data.transaction that hosts support classes for multi-transactions


Issue Links:

spring-projects-issues commented 4 years ago

s-mop commented

Yes, it is a problem when commit fails after the first commit is done, but Is there any suggested replacement workaround or other best practice to handle with multi-transaction scenario? for example different datasource or different data storages.Mark Paluch

spring-projects-issues commented 4 years ago

Mark Paluch commented

From what I see the issue is rooted in how Spring's Transaction Manager works with synchronization. The initial assumption is, there's a single transaction manager that takes care of resources and synchronizations. Hence, all integrations interact with TransactionSynchronizationManager which is backed by singleton ThreadLocals. Since it never was required to qualify synchronizations and resources with an owing transaction manager, all of these are mixed and we're not able to sort out transactional resources.

Typically, transactional integrations bind their DataSource (or other resources) to the transaction and do not care about the transaction manager. Looking at e.g. DataSourceTransactionManager, the transaction manager is aware of the DataSource while e.g. JdbcTemplate is only aware of the DataSource and not the transaction manager. Going further, DataSourceUtils.getConnecion(…) binds a ConnectionSynchronization to the transaction without the chance to know for which transaction manager the synchronization should apply

spring-projects-issues commented 4 years ago

Kaushik commented

Yes. I am facing this issue in our project. But we use this heavily in our projects.

Just a quick search of public gihub repositories that use this class - https://github.com/search?q=%22org.springframework.data.transaction.ChainedTransactionManager%22&type=Code

Looking at the amount of usages, we need an alternate and much better approach to this

OrangeDog commented 3 years ago

So what should we do when we need to use multiple DataSources in a single @Transactional section? This was the simplest configuration when inconsistent rollbacks (i.e. one commits while another rolls-back) were not an issue. Can an example be provided?

softwarebrahma commented 2 years ago

So what should we do when we need to use multiple DataSources in a single @Transactional section? This was the simplest configuration when inconsistent rollbacks (i.e. one commits while another rolls-back) were not an issue. Can an example be provided?

+1 I am interested aswell.

idkw commented 2 years ago

I agree, deprecating stuff without providing a clear migration path (with examples before/after) is not cool

mp911de commented 2 years ago

Introducing a utility that pretends to coordinate distributed transactions was wrong in the first place. Now folks are using ChainedTransactionManager assuming that it does things correctly and wonder why there is no replacement.

A migration path can be that you go full-on XA and 2PC (e.g. using Atomikos Transaction Manager with JTA). Alternatively, you design your business code in a way that considers partially committed transactions. Since this is highly specific to your domain, Spring cannot help here.

OrangeDog commented 2 years ago

assuming that it does things correctly

It does exactly what its documentation says it does, and that's why I'm using it. It's not your fault that people assume it does something else, and that's no reason to remove it.

idkw commented 2 years ago

Introducing a utility that pretends to coordinate distributed transactions was wrong in the first place. Now folks are using ChainedTransactionManager assuming that it does things correctly and wonder why there is no replacement.

A migration path can be that you go full-on XA and 2PC (e.g. using Atomikos Transaction Manager with JTA). Alternatively, you design your business code in a way that considers partially committed transactions. Since this is highly specific to your domain, Spring cannot help here.

I wonder why you assume that I was assuming it does things "correctly". The javadoc is very clear that it does handle transactions separately so that one can commit and another one might fail. I designed my code for idempotence so I just need to retry the whole thing to pass the next time. This feature is useful because it is simple to use and the limitations were very well documented and not misleading at all.

mp911de commented 2 years ago

I wonder why you assume

This is the reception on our side given the history of tickets and StackOverflow question that we have received. We suggest not using ChainedTransactionManager. It can be useful in a niche but for the broader audience it is not a general-purpose TransactionManager. We do not plan to extend or fix any bugs around ChainedTransactionManager and it is no longer maintained. Therefore it is fair to mark it as deprecated.

If this utility works for your arrangement, you're free to copy that code into your codebase and use it as needed.

ddietterich commented 2 years ago

I do not want a global transaction manager across two sources. I want separate transaction managers for separate databases. However, I get bean collisions when I try to define two PlatformTransactionManagers for the different databases. They are never combined in a single transaction.