[ 
https://issues.apache.org/jira/browse/IGNITE-23467?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17896670#comment-17896670
 ] 

Vladislav Pyatkov edited comment on IGNITE-23467 at 11/8/24 7:31 PM:
---------------------------------------------------------------------

The issue is it needs several attempts to reduce all locks on a single key in 
case the lock holders go out of topology.
The resolution is:
 # To add all patential holders to the lock event arguments 
({_}LockEvent.LOCK_CONFLICT{_}).
The way to get all the patential holders: waiters
_LockEventParameters#patentialHolders : List<UUID>_
 # In case the conflicted lockholder ({_}params.lockHolderTx{_}) has gone out 
of toppology, the orphan detector would check all the potential holders 
({_}params.patentialHolders{_}).
 # It sends the recovery message to all transaction coordinators that have left 
the topology.
# Enrich the recovery message (_TxRecoveryMessage_) to possibly pass several 
transaction ids.

 
 


was (Author: v.pyatkov):
The issue is it needs several attempts to reduce all locks on a single key in 
case the lock holders go out of topology.
The resolution is:
 # To add all patential holders to the lock event arguments 
({_}LockEvent.LOCK_CONFLICT{_}).
The way to get all the patential holders: _waiters.tailMap(tmp.txId(), false)_
_LockEventParameters#patentialHolders : List<UUID>_
 # In case the conflicted lockholder ({_}params.lockHolderTx{_}) has gone out 
of toppology, the orphan detector would check all the potential holders 
({_}params.patentialHolders{_}).
 # It sends the recovery message to all transaction coordinators that have left 
the topology.

 
 

> Resolve all abandoned locks for the key at a time
> -------------------------------------------------
>
>                 Key: IGNITE-23467
>                 URL: https://issues.apache.org/jira/browse/IGNITE-23467
>             Project: Ignite
>          Issue Type: Improvement
>            Reporter: Alexander Lapin
>            Priority: Major
>              Labels: ignite-3
>
> h3. Motivation
> Currently only first abandoned lock will be resolved within abandoned lock 
> resolution process. Precisely only one transaction that holds that lock will 
> be resolved. That will work way ineffective in case of chain of multiple 
> abandoned locks, e.g. S locks acquired by different transacions.
> h3. Definition of Done
>  * Any abandoned lock resolution procedure (and currently we have only one - 
> another tx touch) should resolve whole chain of locks for the touched entity.
> *Reproducer (put in ItTransactionRecoveryTest)*
> {code:java}
> @Test
> public void testMultipleAbandonedTxsAreAborted() throws Exception {
>     TableImpl tbl = unwrapTableImpl(node(0).tables().table(TABLE_NAME));
>     var tblReplicationGrp = new TablePartitionId(tbl.tableId(), PART_ID);
>     String leaseholder = waitAndGetLeaseholder(node(0), tblReplicationGrp);
>     IgniteImpl commitPartNode = findNodeByName(leaseholder);
>     log.info("Transaction commit partition is determined [node={}].", 
> commitPartNode.name());
>     IgniteImpl txCrdNode = nonPrimaryNode(leaseholder);
>     log.info("Transaction coordinator is chosen [node={}].", 
> txCrdNode.name());
>     RecordView<Tuple> view = 
> txCrdNode.tables().table(TABLE_NAME).recordView();
>     view.upsert(null, Tuple.create().set("key", 42).set("val", "val1"));
>     List<InternalTransaction> txns = new ArrayList<>();
>     for (int i = 0; i < 10; i++) {
>         InternalTransaction tx = (InternalTransaction) 
> txCrdNode.transactions().begin();
>         Tuple ignored = view.get(tx, Tuple.create().set("key", 42));
>         txns.add(tx);
>     }
>     LockManager lockManager = commitPartNode.txManager().lockManager();
>     for (InternalTransaction txn : txns) {
>         Iterator<Lock> locks = lockManager.locks(txn.id());
>         assertTrue(locks.hasNext());
>     }
>     txCrdNode.stop();
>     assertTrue(waitForCondition(
>             () -> node(0).clusterNodes().stream().filter(n -> 
> txCrdNode.id().equals(n.id())).count() == 0,
>             10_000));
>     InternalTransaction conflictTx = (InternalTransaction) 
> node(0).transactions().begin();
>     runConflictingTransaction(node(0), conflictTx);
>     // Test if all abandoned transactions are aborted.
>     for (InternalTransaction txn : txns) {
>         assertTrue(
>                 waitForCondition(() -> txStoredState(commitPartNode, 
> txn.id()) == TxState.ABORTED, 10_000),
>                 txns.stream().map(tx -> IgniteStringFormatter.format(
>                         "\n{} -> {}",
>                         tx.id(),
>                         txStoredMeta(commitPartNode, tx.id())
>                 )).collect(Collectors.joining(","))
>         );
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to