Consider thread *Th1* started transaction *Tx1*, done some actions, and is
calling commit (GridNearTxLocal#commit -> commitNearTxLocalAsync). And
concurrently thread *Th2 *is calling the same commit on* Tx1*. Now, if you
look into code :
public IgniteInternalFuture<IgniteInternalTx> commitNearTxLocalAsync() {
if (log.isDebugEnabled())
log.debug("Committing near local tx: " + this);
if (fastFinish()) {
state(PREPARING);
state(PREPARED);
state(COMMITTING);
cctx.tm().fastFinishTx(this, true);
state(COMMITTED);
return new GridFinishedFuture<>((IgniteInternalTx)this);
}
final IgniteInternalFuture<?> prepareFut = prepareNearTxLocal();//1
GridNearTxFinishFuture fut = commitFut;
if (fut == null &&
!COMMIT_FUT_UPD.compareAndSet(this, null, fut = new
GridNearTxFinishFuture<>(cctx, this, true)))
return commitFut;//2
cctx.mvcc().addFuture(fut, fut.futureId());//3
Both threads would end up on //1 .Then.
*Th1 *would create *commitFut* in //2 and add it to mvcc //3
*Th2 *concurrently would evaluate //2 into true(it sees fut not null now)
and put fut into mvcc //3 which would lead to exception.
So, there is no locking sections (mutex) here
---------- Forwarded message ---------
From: Yakov Zhdanov <[email protected]>
Date: пн, 3 июл. 2017 г. в 14:16
Subject: Re: Support for starting transaction in another thread IGNITE-4887
To: ALEKSEY KUZNETSOV <[email protected]>
Alex, what do you mean by "multiple threads committing?". Transaction
should be committed only by one thread and only once.
Can you please provide a test or a code snippet to demonstrate the issue
you mentioned.
--Yakov
Im looking into current implementation of commitNearTxLocalAsync() , and in
case of multiple concurrent threads committing there would be exception
thrown by
cctx.mvcc().addFuture(fut, fut.futureId());
Is it correct behavior ?
--
*Best Regards,*
*Kuznetsov Aleksey*