luwei16 commented on code in PR #66178:
URL: https://github.com/apache/doris/pull/66178#discussion_r4281761327


##########
fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java:
##########
@@ -3163,13 +3164,38 @@ private void cancelColumnJob(CancelAlterTableCommand 
command) throws DdlExceptio
             schemaChangeJobV2 = schemaChangeJobV2List.size() == 0 ? null
                     : Iterables.getOnlyElement(schemaChangeJobV2List);
             if (schemaChangeJobV2 == null) {
-                throw new DdlException(
-                    "Table[" + tableName + "] is under schema change state" + 
" but could not find related job");
+                if (olapTable.getState() == OlapTableState.WAITING_STABLE) {
+                    // WAITING_STABLE but no live job: an orphaned state 
produced by an old binary that
+                    // cancelled a still-WAITING_STABLE job without resetting 
the table (the job's
+                    // cancelInternal already dropped the shadow indexes, only 
the table state was left
+                    // stuck). Self-heal by resetting to NORMAL so the table 
is usable again instead of
+                    // leaving DROP TABLE as the only escape. The reset is 
done durably via
+                    // setTableStatusInternal (edit log + follower replay), so 
we only flag it here and
+                    // perform it after releasing the table lock.
+                    healOrphanedWaitingStable = true;
+                } else {
+                    // SCHEMA_CHANGE with no backing job is not a 
known-reachable state; a silent reset
+                    // could abandon still-present shadow indexes/tablets. 
Keep failing loudly so it is
+                    // investigated rather than masked.
+                    throw new DdlException("Table[" + tableName + "] is under 
SCHEMA_CHANGE"
+                            + " but could not find related job");
+                }
             }
         } finally {
             olapTable.writeUnlock();
         }
 
+        if (healOrphanedWaitingStable) {
+            LOG.warn("table[{}] is in state WAITING_STABLE but has no related 
schema change job, "
+                    + "reset table state to NORMAL", tableName);
+            try {
+                Env.getCurrentEnv().setTableStatusInternal(dbName, tableName, 
OlapTableState.NORMAL, false);

Review Comment:
   **Make orphan validation and the state reset atomic**
   
   The table lock is released before this reset, and `setTableStatusInternal()` 
does not revalidate the orphan condition. Two concurrent CANCEL requests can 
both observe the same orphaned state. After one restores `NORMAL`, a new 
schema-change job can be submitted and advance to `WAITING_TXN`. The other 
CANCEL can then overwrite that job’s `SCHEMA_CHANGE` table state with `NORMAL`, 
causing `runWaitingTxnJob()` to fail its state check and cancel the new job.
   
   Please perform the final state and unfinished-job checks together with the 
reset under the same table lock, and add a concurrent-recovery test to cover 
this interleaving.



##########
fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java:
##########
@@ -3163,13 +3164,38 @@ private void cancelColumnJob(CancelAlterTableCommand 
command) throws DdlExceptio
             schemaChangeJobV2 = schemaChangeJobV2List.size() == 0 ? null
                     : Iterables.getOnlyElement(schemaChangeJobV2List);
             if (schemaChangeJobV2 == null) {
-                throw new DdlException(
-                    "Table[" + tableName + "] is under schema change state" + 
" but could not find related job");
+                if (olapTable.getState() == OlapTableState.WAITING_STABLE) {

Review Comment:
   **Check for active rollup jobs before treating WAITING_STABLE as orphaned**
   
   `WAITING_STABLE` is shared by schema-change and rollup jobs, but 
`getUnfinishedAlterJobV2ByTableId()` only searches this `SchemaChangeHandler` 
instance’s jobs. When a live rollup is waiting for the table to become stable, 
`CANCEL ALTER TABLE COLUMN` therefore finds no schema-change job and 
incorrectly resets the table to `NORMAL`, while the rollup remains `PENDING`.
   
   This allows conflicting operations such as another schema change or `DROP 
PARTITION` to proceed against a table with an active rollup. Please also check 
for unfinished jobs in `MaterializedViewHandler` before declaring the state 
orphaned, and add a test covering COLUMN cancellation while a rollup is waiting 
for stability.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to