From f10eb1600863b83d6708620464315539d4914eb9 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Mon, 24 Feb 2025 07:59:51 -0600 Subject: [PATCH] allow SHOW to stop blocking queries after a VT15001 Signed-off-by: Florent Poinsard --- .../newfeaturetest/reparent_in_tx_test.go | 2 +- go/vt/vterrors/code.go | 4 ++-- go/vt/vtgate/executor.go | 1 - go/vt/vtgate/plan_execute.go | 15 +++++++++++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/go/test/endtoend/reparent/newfeaturetest/reparent_in_tx_test.go b/go/test/endtoend/reparent/newfeaturetest/reparent_in_tx_test.go index 31426092198..e7be5ad6e2d 100644 --- a/go/test/endtoend/reparent/newfeaturetest/reparent_in_tx_test.go +++ b/go/test/endtoend/reparent/newfeaturetest/reparent_in_tx_test.go @@ -68,7 +68,7 @@ func testExecuteError(t *testing.T, conn *mysql.Conn, clusterInstance *cluster.L _, err = conn.ExecuteFetch("select * from vt_insert_test", 1, false) require.ErrorContains(t, err, "VT15002") - _, err = conn.ExecuteFetch("rollback", 0, false) + _, err = conn.ExecuteFetch("show warnings", 0, false) require.NoError(t, err) executeDone <- true }() diff --git a/go/vt/vterrors/code.go b/go/vt/vterrors/code.go index 8a086530d4e..0a67e936454 100644 --- a/go/vt/vterrors/code.go +++ b/go/vt/vterrors/code.go @@ -121,8 +121,8 @@ var ( VT14004 = errorWithoutState("VT14004", vtrpcpb.Code_UNAVAILABLE, "cannot find keyspace for: %s", "The specified keyspace could not be found.") VT14005 = errorWithoutState("VT14005", vtrpcpb.Code_UNAVAILABLE, "cannot lookup sidecar database for keyspace: %s", "Failed to read sidecar database identifier.") - VT15001 = errorWithNoCode("VT15001", "transient transaction error, please issue a ROLLBACK and retry the transaction: %s", "The opened transaction must be ROLLBACK by the application and re-tried.") - VT15002 = errorWithoutState("VT15002", vtrpcpb.Code_FAILED_PRECONDITION, "previous transaction failed fatally: issue a ROLLBACK query in order to acknowledge the failed transaction", "This error appears after a VT15001 error was sent back to the client, future queries on the same session will fail until a ROLLBACK is explicitly sent to VTGate.") + VT15001 = errorWithNoCode("VT15001", "transient transaction error, please issue a ROLLBACK or SHOW WARNINGS and retry the transaction: %s", "The opened transaction must be ROLLBACK by the application and re-tried.") + VT15002 = errorWithoutState("VT15002", vtrpcpb.Code_FAILED_PRECONDITION, "previous transaction failed fatally: issue a ROLLBACK or SHOW WARNINGS query in order to acknowledge the failed transaction", "This error appears after a VT15001 error was sent back to the client, future queries on the same session will fail until the client acknowledge the situation by a sending a ROLLBACK or SHOW WARNINGS query.") // Errors is a list of errors that must match all the variables // defined above to enable auto-documentation of error codes. diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index a998b19f36a..d6f53984650 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -625,7 +625,6 @@ func (e *Executor) handleRollback(ctx context.Context, safeSession *econtext.Saf e.updateQueryCounts("Rollback", "", "", int64(logStats.ShardQueries)) err := e.txConn.Rollback(ctx, safeSession) logStats.CommitTime = time.Since(execStart) - safeSession.SetErrorUntilRollback(false) // We have executed a ROLLBACK, if applicable: we can stop blocking queries on this session return &sqltypes.Result{}, err } diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index 422bac6b3ec..05c7eff0779 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -152,8 +152,8 @@ func (e *Executor) newExecute( ctx, cancel = vcursor.GetContextWithTimeOut(ctx) defer cancel() - // If we have previously issued a VT15001 error, we block every queries on this session until we receive a ROLLBACK. - if plan.Type != sqlparser.StmtRollback && safeSession.IsErrorUntilRollback() { + // If we have previously issued a VT15001 error, we block every queries on this session until we receive a ROLLBACK or "show warnings". + if shouldBlockQuery(plan, safeSession) { return vterrors.VT15002() } @@ -444,3 +444,14 @@ func (e *Executor) logPlanningFinished(logStats *logstats.LogStats, plan *engine logStats.PlanTime = execStart.Sub(logStats.StartTime) return execStart } + +func shouldBlockQuery(plan *engine.Plan, safeSession *econtext.SafeSession) bool { + block := safeSession.IsErrorUntilRollback() + if plan.Type != sqlparser.StmtRollback && plan.Type != sqlparser.StmtShow && block { + return true + } + if block { + safeSession.SetErrorUntilRollback(false) + } + return false +}