morningman commented on code in PR #69566:
URL: https://github.com/apache/doris/pull/69566#discussion_r4366909793


##########
fe/fe-core/src/main/java/org/apache/doris/qe/MysqlConnectProcessor.java:
##########
@@ -281,6 +285,21 @@ protected void handleExecute(PrepareCommand 
prepareCommand, long stmtId, Prepare
         }
     }
 
+    /**
+     * COM_STMT_EXECUTE has no per-statement close like the one COM_QUERY runs 
in its finally. An execution that
+     * fails after its scans were planned, such as one a scan-level SQL block 
rule rejects or a prepared
+     * INSERT ... SELECT whose transaction fails to begin, never reaches 
unregisterQuery: the query-finish callbacks
+     * its scans registered (releasing a connector read transaction, closing 
the connector scope) would stay in the
+     * registry for good, its connector scope would stay open until the 
statement's next EXECUTE, and scan nodes left
+     * for the statement end would never stop. The context ExecuteCommand ran 
this execution with is the prepared
+     * statement's current one (see 
PreparedStatementContext#nextStatementContext). Both calls are no-ops for an
+     * execution that finished normally, which already unregistered its query 
and closed its scope.
+     */
+    private void finishExecution(PreparedStatementContext prepCtx) {
+        QeProcessorImpl.INSTANCE.unregisterQuery(ctx.queryId());

Review Comment:
   Thanks, the race is real, but this PR neither introduces nor widens it.
   
   - It comes from two things this PR does not touch: `SplitProducer.close()` 
only sets `cancelled` and does not wait for a run that is already past that 
check, and `ConnectorStatementScopeImpl.computeIfAbsent` ignores `closed`, so a 
value loaded after `closeAll()` is kept and never closed.
   - `finishExecution` runs the sequence every other statement already runs: 
`unregisterQuery` (the stop callback, then `QueryFinishCleanup`, in the order 
`startSplit` registers them), then `StatementContext.close()`. That is 
`finalizeQuery` followed by ConnectProcessor's per-statement finally for 
COM_QUERY, and `TaskProcessor.closeTaskContext` for job tasks.
   - In the case you describe, COM_QUERY is more exposed today. A first-split 
timeout is a planning failure, which never reaches `unregisterQuery` on 
COM_QUERY, so the producer is not cancelled at all while 
`StatementContext.close()` closes the scope: even a producer still queued at 
the timeout later loads into the closed scope, and it keeps its split source 
and its registry entry. With this PR, EXECUTE cancels the producer first, so 
only a producer that is already past its cancellation check can still reach the 
scope.
   - Before this PR the same EXECUTE never ran its stop callback or 
`QueryFinishCleanup`: the registry entry stayed for good, the producer was 
never cancelled, and the scope closed only if the statement was executed again. 
The sub-case where that later close released the lease is the only one that 
changes.
   
   Closing the window needs the scope/producer contract fixed for every 
statement kind: a closed scope that rejects (and closes) late values, which 
first needs the cloud replan retry to stop reusing a closed scope, or a scope 
close that waits for the producers to quiesce. I'd rather do that as a separate 
change than in this PR.
   



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