[
https://issues.apache.org/jira/browse/IGNITE-23467?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Alexey Scherbakov updated IGNITE-23467:
---------------------------------------
Description:
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 < 1; 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));
}
}{code}
was:
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.
> 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 < 1; 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));
> }
> }{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)