Skip to content

Commit fd07a0d

Browse files
committed
[BugFix] When replica enter decommission, transaction will nerver complete (#49349)
1 parent 9cbc820 commit fd07a0d

3 files changed

Lines changed: 26 additions & 4 deletions

File tree

fe/fe-core/src/main/java/com/starrocks/transaction/DatabaseTransactionMgr.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,8 +930,7 @@ public void finishTransaction(long transactionId, Set<Long> errorReplicaIds) thr
930930
if (!errorReplicaIds.contains(replica.getId())
931931
&& replica.getLastFailedVersion() < 0) {
932932
// if replica not commit yet, skip it. This may happen when it's just create by clone.
933-
if (!transactionState.tabletCommitInfosContainsReplica(tablet.getId(),
934-
replica.getBackendId(), replica.getState())) {
933+
if (transactionState.checkReplicaNeedSkip(tablet, replica, partitionCommitInfo)) {
935934
continue;
936935
}
937936
// this means the replica is a healthy replica,

fe/fe-core/src/main/java/com/starrocks/transaction/OlapTableTxnLogApplier.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ public void applyVisibleLog(TransactionState txnState, TableCommitInfo commitInf
104104
long lastFailedVersion = replica.getLastFailedVersion();
105105
long newVersion = version;
106106
long lastSucessVersion = replica.getLastSuccessVersion();
107-
if (!txnState.tabletCommitInfosContainsReplica(tablet.getId(), replica.getBackendId(),
108-
replica.getState())
107+
if (txnState.checkReplicaNeedSkip(tablet, replica, partitionCommitInfo)
109108
|| errorReplicaIds.contains(replica.getId())) {
110109
// There are 2 cases that we can't update version to visible version and need to
111110
// set lastFailedVersion.

fe/fe-core/src/main/java/com/starrocks/transaction/TransactionState.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@
4545
import com.starrocks.catalog.MaterializedIndex;
4646
import com.starrocks.catalog.OlapTable;
4747
import com.starrocks.catalog.Partition;
48+
import com.starrocks.catalog.Replica;
4849
import com.starrocks.catalog.Replica.ReplicaState;
50+
import com.starrocks.catalog.Tablet;
4951
import com.starrocks.common.Config;
5052
import com.starrocks.common.TraceManager;
5153
import com.starrocks.common.UserException;
@@ -386,6 +388,28 @@ public void setTabletCommitInfos(List<TabletCommitInfo> infos) {
386388
this.tabletCommitInfos.addAll(infos);
387389
}
388390

391+
public boolean checkReplicaNeedSkip(Tablet tablet, Replica replica, PartitionCommitInfo partitionCommitInfo) {
392+
boolean isContain = tabletCommitInfosContainsReplica(tablet.getId(), replica.getBackendId(), replica.getState());
393+
if (isContain) {
394+
return false;
395+
}
396+
397+
// In order for the transaction to complete in time for this scenario: the server machine is not recovered.
398+
// 1. Transaction TA writes to a two-replicas tablet and enters the committed state.
399+
// The tablet's repliace are replicaA, replicaB.
400+
// 2. replicaA, replicaB generate tasks: PublishVersionTaskA, PublishVersionTaskB.
401+
// PublishVersionTaskA/PublishVersionTaskB successfully submitted to the beA/beB via RPC.
402+
// 3. The machine where beB is located hangs and is not recoverable.
403+
// Therefore PublishVersionTaskA is finished,PublishVersionTaskB is unfinished.
404+
// 4. FE clone replicaC from replicaA, BE report replicaC info.
405+
// So transactions must rely on replicaA and replicaC to accomplish visible state.
406+
if (replica.getVersion() >= partitionCommitInfo.getVersion()) {
407+
return false;
408+
}
409+
410+
return true;
411+
}
412+
389413
public boolean tabletCommitInfosContainsReplica(long tabletId, long backendId, ReplicaState state) {
390414
TabletCommitInfo info = new TabletCommitInfo(tabletId, backendId);
391415
if (this.tabletCommitInfos == null) {

0 commit comments

Comments
 (0)