[
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)