I understand the fact that a transaction that spans multiple transactional resources is called a global transaction.
Question 1:
Is this just an another name for distributed transaction or is that something different?
Question 2:
Have gone through spring's documentation on Transaction Management.
What i could infer from that is
a. JTA is purely designed for distributed transactions.
b. Only through EJBs and EJB CMT, we could enforce distributed transactions.
c. If EJBs, then it mandates an Application Server and indirectly JNDI too.
What is Spring's counterpart to facilitate global/distributed transactions?
Question 3:
If we don't want to go with an application server with JTA capability,
should we be using Atomikos / JOTM like standalone Transaction managers to enforce global transactions?
Question 4:
A simple usecase of updating Table A in DB_1 (MySql) and Table B in DB_2 (Oracle) under a single transaction:
What is Spring's answer to this usecase?
Yes
a) No, not every transaction will be distributed, only if more than one resource is involved. The TM handles the management of the transactions executed on the involved resources
b) No, there are transactionsmanagers usable outside ejb-servers like atomikos, bitronix,... but I am not sure what you mean by enforce, as I wrote earlier, distributed transactions are used when necessary.
c) yes
d) Springs counterpart
if you want to use transactions on multiple resources at the same time yes.
you define two datasources in a way, that they let a TM handle their resources. Both MySql and Oracle provide XA-Datasources which allow it to handle distributed transactions. You define a TM and make it possible to annotate your beans with Transaction Attributes. There are many tutorials out there which show how this can be done.
Additional remarks:
Meanwhile transactions are also included in the CDI-Spec. So you can also use CDI.
Handle the distributed transactions wisely. The two way commit makes it almost impossible to set a reasonable transaction timeout. There are development-sites where distributed transactions only are used between one SQL-DBMS-Resource and one JMS-Resource if necessary.
Related
I am trying to create an API in Spring Boot using #Transactional annotation regarding bank fund transfer.
Now I want to know - if there are multiple calls to the same API at the same time, how to manage transaction between them. Suppose for example transferBalance method is called by Transaction X which transfers funds from accounts A to B and another transaction Transaction Y transfer funds from B to C. Both transactions occur at the same time. How would these transactions be handled? What propagation should it have and also what about the isolation?
Check this below changes: for your case check bold description below.
if more than one transaction can also go with SERIALIZED
Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions. When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.
#Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {
}
READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions.
READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions.
REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same.
SERIALIZABLE isolation level is the most restrictive of all isolation levels. Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.
Your doubt has nothing to do with #Transactional.
Its simple question of concurrency.
Actually both the transaction, form a to b and form b to c can work concurrently.
By putting #Transactional states something like
works out whether a given exception should cause transaction rollback by applying a number of rollback rules, both positive and negative. If no rules are relevant to the exception, it behaves like DefaultTransactionAttribute (rolling back on runtime exceptions).
I am beginner to spring , now in my project we have method to make booking ,now if the available booking is 1 , when two user are trying booking at same time ideally only one booking is allowed , but my application is allowing two bookings, now i made the method as synchronized now it is working fine, but synchronization concept belongs to JVM now if I am configuring my application in cluster mode there are different servers in different machines(so different JVMS), now synchronization wont work.
Can any one please tell me the possible solution for this to restrict the booking,tell me solution from JAVA side and and also from DB side
If the application may be deployed in cluster, the synchronized method will indeed not be enough.
You should rely on a node shared by all server instances : the DB.
You could use DB locking features, especially optimistic locking and pessimistic locking.
With them, you could avoid collisions resulting from concurrent updates to the same line by concurrent clients.
Choose which one that matches better to your use case.
Concurrency control in databases extract:
Optimistic - Delay the checking of whether a transaction meets the
isolation and other integrity rules (e.g., serializability and
recoverability) until its end, without blocking any of its (read,
write) operations ("...and be optimistic about the rules being
met..."), and then abort a transaction to prevent the violation, if
the desired rules are to be violated upon its commit. An aborted
transaction is immediately restarted and re-executed, which incurs an
obvious overhead (versus executing it to the end only once). If not
too many transactions are aborted, then being optimistic is usually a
good strategy.
Pessimistic - Block an operation of a transaction, if
it may cause violation of the rules, until the possibility of
violation disappears. Blocking operations is typically involved with
performance reduction.
JDBC and JPA support both.
You should try with ETags - optimistic locking mechanism.
It can be easily implemented with Spring. Please check official documentation.
Hope this will help.
I Have two mico-serives A and B where they connect to seperate database, From Mico-serives A i need to persist(save) objects of both A and B in same transtation how to achive this.
I am using Spring micro-servies with netflix-oss.Please give suggestions on best way to do achive 2 phase commit.
you can not implement traditional transaction system in micro-services in a distributed environment.
You should you Event Sourcing + CQRS technique and because they are atomic you will gain something like implementing transactions or 2PC in a monolithic system.
Other possible way is transaction-log-mining that I think linked-in is using this way but it has its own cons and pros. for e.g. binary log of different databases are different and event in same kind of database there are differences between different versions.
I suggest that you use Event Sourcing + CQRS and string events in an event-store then try reaching eventual consistency base on CAP theorem after transferring multiple events between micro-service A and B and updating domain states in each step.
It is suggested that you use a message broker like ActiveMQ, RabbitMQ or Kafka for sending event-sourced events between different microservices and string them in an event store like mysql or other systems.
Another benefit of this way beside mimicking transactions is that you will have a complete audit log.
It is an architecture(microservices) problem. Spring boot or netflix-oss do not offer a direct solution. You have to implement your own solution. Check with event driven architecture. It can give you some ideas.
You could try the SAGA pattern https://microservices.io/patterns/data/saga.html
I refer to the example stated in the URL which is to apply spring aop transaction across all methods in service layers, but this will also apply transaction management for read-only methods like SELECT.
Is there any adverse effect, if I apply transaction management for readOnly transaction?
<aop:config>
<aop:advisor pointcut="execution(* com.xyz.someapp.service.*.*(..)))"
advice-ref="transactionAdvice" />
</aop:config>
http://www.studytrails.com/frameworks/spring/spring-declarative-transactions.jsp
I have another question. If I have orderService.create() which invokes billingService.create(), how will the transaction isolation be applied?
You generally want to use transactions even for read-only operations, since a transaction will give you a consistent view of your data. If you skip transactions, you risk seeing partial updates from some other incomplete transaction.
I dont't think that there will be any adverse effects because a transaction simply defines an atomic set of operations. If a transaction fails then a rollback will be performed, but read-only operations don't affect the database in any way.
The only big disadvantage I can think of is related to performance. The locking-strategy of the underlying database (whether table or row is locked) determines your isolation level. Acoording to your locking-strategy some kind of isolation is applied during the transaction. For example, when you're writing to a database your isolation level decides if the changes in progress could be seen by parallel reads (causing e.g. dirty reads, non-repeatable reads and so on) or if these changes have to be commited before they become visible to others.
As a consequence you would lock resources you only want to read, which could be performance overkill on highly available applications. Summing up: It doesn't have bad effects aside from causing performance issues.
Addressing your second question: This depends on how you're managing transactions. I guess in this case both service methods require transactions, so I think the default behavior is that the transaction of the first service call is inherited by the second service method call (this is called 'transaction propagation'). This is required because nested transactions aren't allowed.
If I am using "transaction-type" JTA in "persistence.xml" ,
then is it mandatory to use XA type data sources in "" element ?
or we can also using simple data source also .
Thanks !!
That depends. If you want to use JTA and have multiple participants (i.e. datasources, jms connections etc) then you really must have an XA capable datasource. When you don't have this you have problems starting a distributed transaction.
If this is the only participant ever then you might even wonder why do you want JTA transactions and stick with resource local transactions.