Repository: pingcap/tidb
File: pkg/executor/adapter.go (Go)

Code before:
			TxnTS:      txnTS,
			User:       userString,
			DB:         sessVars.CurrentDB,
			TableIDs:   tableIDs,
			IndexNames: slowItems.IndexNames,
			Internal:   sessVars.InRestrictedSQL,
		})
	}
}

func (a *ExecStmt) updateNetworkTrafficStatsAndMetrics() {
	hasMPPTraffic := a.updateMPPNetworkTraffic()
	tikvExecDetailRaw := a.GoCtx.Value(util.ExecDetailsKey)
	if tikvExecDetailRaw != nil {
		tikvExecDetail := tikvExecDetailRaw.(*util.ExecDetails)
		executor_metrics.ExecutorNetworkTransmissionSentTiKVTotal.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesSentKVTotal)))
		executor_metrics.ExecutorNetworkTransmissionSentTiKVCrossZone.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesSentKVCrossZone)))
		executor_metrics.ExecutorNetworkTransmissionReceivedTiKVTotal.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesReceivedKVTotal)))
		executor_metrics.ExecutorNetworkTransmissionReceivedTiKVCrossZone.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesReceivedKVCrossZone)))
		if hasMPPTraffic {
			executor_metrics.ExecutorNetworkTransmissionSentTiFlashTotal.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesSentMPPTotal)))
			executor_metrics.ExecutorNetworkTransmissionSentTiFlashCrossZone.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesSentMPPCrossZone)))
			executor_metrics.ExecutorNetworkTransmissionReceivedTiFlashTotal.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesReceivedMPPTotal)))
			executor_metrics.ExecutorNetworkTransmissionReceivedTiFlashCrossZone.Add(float64(atomic.LoadInt64(&tikvExecDetail.UnpackedBytesReceivedMPPCrossZone)))
		}
	}
}

func (a *ExecStmt) updateMPPNetworkTraffic() bool {
	sessVars := a.Ctx.GetSessionVars()
	stmtCtx := sessVars.StmtCtx
	runtimeStatsColl := stmtCtx.RuntimeStatsColl
	if runtimeStatsColl == nil {
		return false
	}
	tiflashNetworkStats := runtimeStatsColl.GetStmtCopRuntimeStats().TiflashNetworkStats
	if tiflashNetworkStats == nil {
		return false
	}
	tikvExecDetailRaw := a.GoCtx.Value(util.ExecDetailsKey)
	if tikvExecDetailRaw == nil {
		tikvExecDetailRaw = &util.ExecDetails{}
		a.GoCtx = context.WithValue(a.GoCtx, util.ExecDetailsKey, tikvExecDetailRaw)
	}

	tikvExecDetail := tikvExecDetailRaw.(*util.ExecDetails)
	tiflashNetworkStats.UpdateTiKVExecDetails(tikvExecDetail)
	return true
}

// getFlatPlan generates a FlatPhysicalPlan from the plan stored in stmtCtx.plan,

Review comment (suggestion):
From the code execution flow, `FinishExecuteStmt()` is called after `exec.Close()`。Under normal circumstances, `exec.Close()` should wait for all network requests to complete, so when `FinishExecuteStmt()` is called, client-go's goroutines should have already finished processing network responses and should no longer be updating ExecDetails fields.

Could you clarify which specific scenarios this handling in the PR is intended for? Based on the issue description, the problem appears to be caused by an exceptional path (e.g. a panic) rather than a flaw in the normal execution flow.

Code after:
	dom := domain.GetDomain(a.Ctx)
	if dom != nil {
		dom.LogSlowQuery(&domain.SlowQueryInfo{
			SQL:        slowItems.SQL,
			Digest:     slowItems.Digest,
			Start:      sessVars.StartTime,
			Duration:   costTime,
			Detail:     *execDetail,
			Succ:       succ,
			ConnID:     sessVars.ConnectionID,
			SessAlias:  sessVars.SessionAlias,
			TxnTS:      txnTS,
			User:       userString,
			DB:         sessVars.CurrentDB,
			TableIDs:   tableIDs,
			IndexNames: slowItems.IndexNames,
			Internal:   sessVars.InRestrictedSQL,
		})
	}
}

func (a *ExecStmt) updateNetworkTrafficStatsAndMetrics() {
	hasMPPTraffic := a.updateMPPNetworkTraffic()
	tikvExecDetailRaw := a.GoCtx.Value(util.ExecDetailsKey)
	if tikvExecDetailRaw != nil {
		tikvExecDetail := tikvExecDetailRaw.(*util.ExecDetails)
		executor_metrics.ExecutorNetworkTransmissionSentTiKVTotal.Add(float64(tikvExecDetail.UnpackedBytesSentKVTotal))
		executor_metrics.ExecutorNetworkTransmissionSentTiKVCrossZone.Add(float64(tikvExecDetail.UnpackedBytesSentKVCrossZone))
		executor_metrics.ExecutorNetworkTransmissionReceivedTiKVTotal.Add(float64(tikvExecDetail.UnpackedBytesReceivedKVTotal))
		executor_metrics.ExecutorNetworkTransmissionReceivedTiKVCrossZone.Add(float64(tikvExecDetail.UnpackedBytesReceivedKVCrossZone))
		if hasMPPTraffic {
			executor_metrics.ExecutorNetworkTransmissionSentTiFlashTotal.Add(float64(tikvExecDetail.UnpackedBytesSentMPPTotal))
			executor_metrics.ExecutorNetworkTransmissionSentTiFlashCrossZone.Add(float64(tikvExecDetail.UnpackedBytesSentMPPCrossZone))
			executor_metrics.ExecutorNetworkTransmissionReceivedTiFlashTotal.Add(float64(tikvExecDetail.UnpackedBytesReceivedMPPTotal))
			executor_metrics.ExecutorNetworkTransmissionReceivedTiFlashCrossZone.Add(float64(tikvExecDetail.UnpackedBytesReceivedMPPCrossZone))
		}
	}
}

func (a *ExecStmt) updateMPPNetworkTraffic() bool {
	sessVars := a.Ctx.GetSessionVars()
	stmtCtx := sessVars.StmtCtx
	runtimeStatsColl := stmtCtx.RuntimeStatsColl
	if runtimeStatsColl == nil {
		return false
	}
	tiflashNetworkStats := runtimeStatsColl.GetStmtCopRuntimeStats().TiflashNetworkStats
	if tiflashNetworkStats == nil {
		return false
	}
	tikvExecDetailRaw := a.GoCtx.Value(util.ExecDetailsKey)