Skip to content

onlineddl: context-scoped bulk migration operations#20147

Open
shlomi-noach wants to merge 13 commits into
vitessio:mainfrom
planetscale:onlineddl-context-operations
Open

onlineddl: context-scoped bulk migration operations#20147
shlomi-noach wants to merge 13 commits into
vitessio:mainfrom
planetscale:onlineddl-context-operations

Conversation

@shlomi-noach
Copy link
Copy Markdown
Contributor

@shlomi-noach shlomi-noach commented May 20, 2026

Followup to #20146, similar changes (same changes parser-wise, obviously different implementation onlineddl-executor-wise).

Fixes #20177.
Related: #20145

Extends the ALTER VITESS_MIGRATION ... CONTEXT 'ctx' pattern to all bulk migration operations. Previously only CANCEL CONTEXT 'ctx' existed. Now the full set is supported:

ALTER VITESS_MIGRATION CANCEL CONTEXT 'ctx'
ALTER VITESS_MIGRATION CLEANUP CONTEXT 'ctx'
ALTER VITESS_MIGRATION COMPLETE CONTEXT 'ctx'
ALTER VITESS_MIGRATION POSTPONE COMPLETE CONTEXT 'ctx'
ALTER VITESS_MIGRATION FORCE_CUTOVER CONTEXT 'ctx'
ALTER VITESS_MIGRATION LAUNCH CONTEXT 'ctx'
ALTER VITESS_MIGRATION THROTTLE CONTEXT 'ctx' [EXPIRE 'duration'] [RATIO ratio]
ALTER VITESS_MIGRATION UNTHROTTLE CONTEXT 'ctx'

Each operation affects only migrations belonging to the given migration_context, leaving unrelated contexts untouched.

How it works

The AlterMigration AST node already carries a Context string field (added in the CANCEL CONTEXT PR). Each XxxAllMigrationType executor method now accepts an optional migrationContext string parameter:

  • Empty → existing bulk behavior (unchanged)
  • Non-empty → filters to migrations matching that context

CLEANUP CONTEXT uses a new SQL constant that adds AND migration_context=? to the existing cleanup query. All other operations iterate readPendingMigrations and skip non-matching contexts, matching the pattern established by CancelPendingMigrations.

THROTTLE/UNTHROTTLE CONTEXT work by iterating pending migrations in the context and throttling each by UUID (the individual-migration throttle path), since the whole-app throttle doesn't support context filtering.

Changes

  • go/vt/sqlparser/ — 7 new grammar rules, format branching for all ALL types, 11 parse round-trip tests
  • go/vt/vttablet/onlineddl/executor.gomigrationContext param on all 7 "All" methods
  • go/vt/vttablet/onlineddl/schema.gosqlUpdateReadyForCleanupAllByContext constant
  • go/vt/vttablet/tabletserver/query_executor.go — pass alterMigration.Context in all ALL-type dispatch cases
  • go/test/endtoend/onlineddl/ — 7 new vtgate helpers + e2e scheduler tests for each operation

Most of this was written by Claude Code — I provided direction.

Copilot AI review requested due to automatic review settings May 20, 2026 08:51
@vitess-bot vitess-bot Bot added NeedsWebsiteDocsUpdate What it says NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request labels May 20, 2026
@github-actions github-actions Bot added this to the v25.0.0 milestone May 20, 2026
@vitess-bot vitess-bot Bot added the NeedsBackportReason If backport labels have been applied to a PR, a justification is required label May 20, 2026
@vitess-bot
Copy link
Copy Markdown
Contributor

vitess-bot Bot commented May 20, 2026

Review Checklist

Hello reviewers! 👋 Please follow this checklist when reviewing this Pull Request.

General

  • Ensure that the Pull Request has a descriptive title.
  • Ensure there is a link to an issue (except for internal cleanup and flaky test fixes), new features should have an RFC that documents use cases and test cases.

Tests

  • Bug fixes should have at least one unit or end-to-end test, enhancement and new features should have a sufficient number of tests.

Documentation

  • Apply the release notes (needs details) label if users need to know about this change.
  • New features should be documented.
  • There should be some code comments as to why things are implemented the way they are.
  • There should be a comment at the top of each new or modified test to explain what the test does.

New flags

  • Is this flag really necessary?
  • Flag names must be clear and intuitive, use dashes (-), and have a clear help text.

If a workflow is added or modified:

  • Each item in Jobs should be named in order to mark it as required.
  • If the workflow needs to be marked as required, the maintainer team must be notified.

Backward compatibility

  • Protobuf changes should be wire-compatible.
  • Changes to _vt tables and RPCs need to be backward compatible.
  • RPC changes should be compatible with vitess-operator
  • If a flag is removed, then it should also be removed from vitess-operator and arewefastyet, if used there.
  • vtctl command output order should be stable and awk-able.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends ALTER VITESS_MIGRATION ... CONTEXT 'ctx' support from just CANCEL to the full set of bulk migration operations, so bulk actions can be scoped to a specific migration_context without impacting other contexts.

Changes:

  • Extends the SQL grammar/AST formatting to parse + round-trip ... CONTEXT 'ctx' for all bulk operations.
  • Threads migrationContext through OnlineDDL executor “All” operations and filters pending migrations accordingly (plus a context-specific cleanup UPDATE).
  • Adds end-to-end helpers/tests to validate each context-scoped bulk operation.

Reviewed changes

Copilot reviewed 10 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
go/vt/vttablet/tabletserver/query_executor.go Passes alterMigration.Context to OnlineDDL executor bulk-operation dispatch.
go/vt/vttablet/onlineddl/schema.go Adds a context-scoped cleanup UPDATE query constant.
go/vt/vttablet/onlineddl/executor.go Adds migrationContext param to bulk executor methods and filters to matching contexts.
go/vt/sqlparser/sql.y Adds CONTEXT token + grammar rules for context-scoped bulk migration operations.
go/vt/sqlparser/parse_test.go Adds parser round-trip coverage for the new ... CONTEXT statements.
go/vt/sqlparser/keywords.go Registers context keyword/token.
go/vt/sqlparser/cached_size.go Updates cached-size accounting for AlterMigration to include Context.
go/vt/sqlparser/ast.go Adds Context field to the AlterMigration AST node.
go/vt/sqlparser/ast_format.go Formats bulk operations as ... context 'ctx' when Context is set.
go/vt/sqlparser/ast_format_fast.go Adds fast formatting for the new Context field (see review comment about escaping).
go/vt/sqlparser/ast_equals.go Includes Context in AlterMigration equality comparisons.
go/test/endtoend/onlineddl/vtgate_util.go Adds VTGate helper functions for context-scoped operations (see review comment about query construction).
go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go Adds scheduler e2e tests validating context-scoped behavior across operations.
Files not reviewed (3)
  • go/vt/sqlparser/ast_equals.go: Language not supported
  • go/vt/sqlparser/ast_format_fast.go: Language not supported
  • go/vt/sqlparser/cached_size.go: Language not supported
Comments suppressed due to low confidence (7)

go/test/endtoend/onlineddl/vtgate_util.go:253

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// CheckPostponeCompleteContextMigrations postpones completion of all pending migrations with a given context and expects number of affected rows.
// A negative value for expectCount indicates "don't care, no need to check"
func CheckPostponeCompleteContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string, expectCount int) {
	query := fmt.Sprintf("alter vitess_migration postpone complete context '%s'", migrationContext)
	r := VtgateExecQuery(t, vtParams, query, "")

go/test/endtoend/onlineddl/vtgate_util.go:286

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// CheckCancelContextMigrations cancels all pending migrations with a given context and expect number of affected rows
// A negative value for expectCount indicates "don't care, no need to check"
func CheckCancelContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string, expectCount int) {
	cancelQuery := fmt.Sprintf("alter vitess_migration cancel context '%s'", migrationContext)
	r := VtgateExecQuery(t, vtParams, cancelQuery, "")

go/test/endtoend/onlineddl/vtgate_util.go:297

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// CheckCleanupContextMigrations cleans up terminal migrations with a given context and expects number of affected rows.
// A negative value for expectCount indicates "don't care, no need to check"
func CheckCleanupContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string, expectCount int) uint64 {
	query := fmt.Sprintf("alter vitess_migration cleanup context '%s'", migrationContext)
	r := VtgateExecQuery(t, vtParams, query, "")

go/test/endtoend/onlineddl/vtgate_util.go:322

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// CheckLaunchContextMigrations launches all queued postponed migrations with a given context and expects number of affected rows.
// A negative value for expectCount indicates "don't care, no need to check"
func CheckLaunchContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string, expectCount int) {
	query := fmt.Sprintf("alter vitess_migration launch context '%s'", migrationContext)
	r := VtgateExecQuery(t, vtParams, query, "")

go/test/endtoend/onlineddl/vtgate_util.go:343

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// CheckForceCutOverContextMigrations marks all pending migrations with a given context for forced cut-over and expects number of affected rows.
// A negative value for expectCount indicates "don't care, no need to check"
func CheckForceCutOverContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string, expectCount int) {
	query := fmt.Sprintf("alter vitess_migration force_cutover context '%s'", migrationContext)
	r := VtgateExecQuery(t, vtParams, query, "")

go/test/endtoend/onlineddl/vtgate_util.go:493

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// ThrottleContextMigrations throttles all pending migrations with a given context.
func ThrottleContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string) {
	query := fmt.Sprintf("alter vitess_migration throttle context '%s' expire '24h' ratio 1", migrationContext)
	_ = VtgateExecQuery(t, vtParams, query, "")

go/test/endtoend/onlineddl/vtgate_util.go:505

  • This query is built via fmt.Sprintf with migrationContext embedded in quotes; contexts containing quotes/backslashes will break the SQL and can lead to unintended statements. Prefer sqlparser.ParseAndBind with %a + StringBindVariable for migrationContext.
// UnthrottleContextMigrations unthrottles all pending migrations with a given context.
func UnthrottleContextMigrations(t *testing.T, vtParams *mysql.ConnParams, migrationContext string) {
	query := fmt.Sprintf("alter vitess_migration unthrottle context '%s'", migrationContext)
	_ = VtgateExecQuery(t, vtParams, query, "")

Comment thread go/vt/sqlparser/ast_format_fast.go Outdated
Comment thread go/test/endtoend/onlineddl/vtgate_util.go
@shlomi-noach shlomi-noach force-pushed the onlineddl-context-operations branch from 3e170fd to 7700c65 Compare May 20, 2026 09:02
Copilot AI review requested due to automatic review settings May 20, 2026 09:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 14 changed files in this pull request and generated no new comments.

Files not reviewed (3)
  • go/vt/sqlparser/ast_equals.go: Language not supported
  • go/vt/sqlparser/ast_format_fast.go: Language not supported
  • go/vt/sqlparser/cached_size.go: Language not supported

@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 0.84746% with 117 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.05%. Comparing base (70c7a72) to head (120cfc6).
⚠️ Report is 277 commits behind head on main.

Files with missing lines Patch % Lines
go/vt/vttablet/onlineddl/executor.go 0.00% 81 Missing ⚠️
go/vt/sqlparser/ast_format.go 3.33% 29 Missing ⚠️
go/vt/vttablet/tabletserver/query_executor.go 0.00% 7 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (70c7a72) and HEAD (120cfc6). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (70c7a72) HEAD (120cfc6)
1 0
Additional details and impacted files
@@             Coverage Diff             @@
##             main   #20147       +/-   ##
===========================================
- Coverage   69.67%   62.05%    -7.62%     
===========================================
  Files        1614      135     -1479     
  Lines      216793    30725   -186068     
===========================================
- Hits       151044    19067   -131977     
+ Misses      65749    11658    -54091     
Flag Coverage Δ
partial 62.05% <0.84%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shlomi-noach shlomi-noach force-pushed the onlineddl-context-operations branch from 5572440 to f862bc0 Compare May 20, 2026 09:26
Copilot AI review requested due to automatic review settings May 20, 2026 10:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 14 changed files in this pull request and generated 1 comment.

Files not reviewed (3)
  • go/vt/sqlparser/ast_equals.go: Language not supported
  • go/vt/sqlparser/ast_format_fast.go: Language not supported
  • go/vt/sqlparser/cached_size.go: Language not supported

Comment thread go/vt/sqlparser/sql.y
Comment on lines +3825 to +3830
| ALTER comment_opt VITESS_MIGRATION CANCEL CONTEXT STRING
{
$$ = &AlterMigration{
Type: CancelAllMigrationType,
Context: $6,
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK OK you're right and I give up. Empty context is now rejected by the parser. I like this idea better than my original approach.

@shlomi-noach shlomi-noach force-pushed the onlineddl-context-operations branch from a707fc3 to 9a0d463 Compare May 20, 2026 11:16
Copilot AI review requested due to automatic review settings May 20, 2026 11:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 14 changed files in this pull request and generated no new comments.

Files not reviewed (3)
  • go/vt/sqlparser/ast_equals.go: Language not supported
  • go/vt/sqlparser/ast_format_fast.go: Language not supported
  • go/vt/sqlparser/cached_size.go: Language not supported

@shlomi-noach shlomi-noach force-pushed the onlineddl-context-operations branch from 28f157f to 03b669b Compare May 20, 2026 12:38
shlomi-noach and others added 5 commits May 21, 2026 11:01
Introduces `ALTER VITESS_MIGRATION CANCEL CONTEXT 'ctx'` syntax to cancel
all pending migrations belonging to a given migration context, without
affecting migrations from other contexts. Complements the existing CANCEL ALL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
The test was accidentally placed inside testSingleton where t1uuid,
t2uuid, trivialAlterT1Statement, and ddlStrategy are out of scope.
Moved it to the end of testScheduler where those variables are declared.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
For every XxxAllMigrationType executor method, empty migrationContext is
the sentinel for the ALL path. OP CONTEXT '' is therefore equivalent to
OP ALL -- empty context is not a supported filter value. Document this in
each method doc comment and add parse round-trip tests that confirm the
formatter produces the expected ALL form.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
@shlomi-noach shlomi-noach added Type: Enhancement Logical improvement (somewhere between a bug and feature) and removed NeedsBackportReason If backport labels have been applied to a PR, a justification is required labels May 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • go/vt/sqlparser/ast_format_fast.go: Language not supported

Comment thread go/vt/vttablet/onlineddl/executor.go
Comment thread go/vt/vttablet/onlineddl/executor.go Outdated
shlomi-noach and others added 3 commits May 24, 2026 08:27
The refactoring to readPendingMigrations inadvertently widened the ALL
path to include running/ready migrations. Restore sqlSelectQueuedMigrations
as the data source (queued-only) and apply the CONTEXT filter in-loop on
migration_context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
ForceCutOverPendingMigrations, CompletePendingMigrations, and
PostponeCompletePendingMigrations now track a matched counter and log
"done iterating N migrations, matched M" — consistent with the
CancelPendingMigrations pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Previously the test held migrations in queued state via --postpone-launch
and asserted queued status after POSTPONE COMPLETE CONTEXT, which proved
nothing about postpone_completion semantics — the queued state was
maintained by postpone_launch, not postpone_completion.

New flow: set postpone_completion, then launch, wait for running, assert
running persists (ensureStateNotChangedTime), then COMPLETE CONTEXT and
wait for complete. This actually exercises the postpone_completion flag.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 24, 2026 05:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • go/vt/sqlparser/ast_format_fast.go: Language not supported

LaunchMigrations filters via sqlSelectQueuedMigrations which requires
reviewed_timestamp IS NOT NULL. The scheduler sets this in a later
processing cycle after the migration enters queued state, so tests
calling CheckLaunchContextMigrations immediately after
WaitForMigrationStatus(queued) could race.

Add WaitForMigrationReviewedTimestamp helper that polls SHOW
VITESS_MIGRATIONS every second until the field is set, and use it in the
two affected tests instead of a fixed sleep.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
@shlomi-noach shlomi-noach marked this pull request as ready for review May 24, 2026 08:17
Copilot AI review requested due to automatic review settings May 24, 2026 08:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • go/vt/sqlparser/ast_format_fast.go: Language not supported

@promptless
Copy link
Copy Markdown
Contributor

promptless Bot commented May 24, 2026

Promptless prepared a documentation update related to this change.

Triggered by PR #20147

Added documentation for the new context-scoped bulk migration operations (LAUNCH CONTEXT, COMPLETE CONTEXT, POSTPONE COMPLETE CONTEXT, FORCE_CUTOVER CONTEXT, CLEANUP CONTEXT, THROTTLE CONTEXT, and UNTHROTTLE CONTEXT) to the Online DDL audit and control guide, following the existing patterns for the CANCEL CONTEXT syntax.

Review: Document context-scoped bulk migration operations

Copy link
Copy Markdown
Member

@mattlord mattlord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we have CLEANUP CONTEXT use the same exact context matching semantics as the other bulk operations in go/vt/vttablet/onlineddl/schema.go:191-197?

The new cleanup path filters with migration_context=%a in SQL, so it inherits the sidecar table's collation. schema_migrations is CHARSET=utf8mb4 without an explicit binary collation, and the supported MySQL versions today all default to a case-insensitive collation for utf8mb4. The other new context-scoped operations compare pm.migrationContext != migrationContext in Go, which is byte/case-sensitive. Since ValidateMigrationContext allows uppercase, contexts like ctx-a and CTX-a can be treated as distinct by COMPLETE/POSTPONE/CANCEL/LAUNCH/FORCE_CUTOVER/THROTTLE, but CLEANUP CONTEXT 'ctx-a' may mark both contexts for artifact cleanup.

Unless I'm missing something I think that we should either make the SQL cleanup predicate binary/exact, or define/implement context matching as case-insensitive consistently across all of these operations. A regression test with two terminal migrations whose contexts differ only by case would then cover this (maybe it will already pass as I'm missing something).

Otherwise it LGTM!

for _, row := range rows {
uuid := row["migration_uuid"].ToString()
mc := row["migration_context"].ToString()
if migrationContext != "" && migrationContext != mc {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth trimming whitespace from both ends of the strings just in case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When looking to apply that, I realize the same could be said about dozens if not more other locations in the code where any migration context or uuid are involved. I'd say skip this.

shlomi-noach and others added 2 commits May 27, 2026 08:29
main changed isOpen from atomic.LoadInt64(&e.isOpen) to e.isOpen.Load();
take that update while keeping the migrationContext parameter our branch
added to CleanupAllMigrations, ForceCutOverPendingMigrations,
CompletePendingMigrations, PostponeCompletePendingMigrations, and
LaunchMigrations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
sqlUpdateReadyForCleanupAllByContext filtered by migration_context using
the table's default utf8mb4_0900_ai_ci collation (case-insensitive),
while all other CONTEXT operations compare migration_context in Go with
==, which is byte-exact. Use COLLATE utf8mb4_bin in the WHERE clause to
make the SQL predicate case-sensitive without changing the schema.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 27, 2026 05:57
@shlomi-noach
Copy link
Copy Markdown
Contributor Author

Shouldn't we have CLEANUP CONTEXT use the same exact context matching semantics as the other bulk operations in go/vt/vttablet/onlineddl/schema.go:191-197?

That's a good catch. sqlUpdateReadyForCleanupAllByContext is the only query that UPDATEs by migration_context comparison.

In choosing the best approach I saw two alternatives:

  1. Introduce a SELECT query that uses same WHERE clause as sqlUpdateReadyForCleanupAllByContext, then compare migration context in golang space, then run one UPDATE query per matched entry; or:
  2. Modify the sqlUpdateReadyForCleanupAllByContext query to be case sensitive.

I picked the latter

diff --git a/go/vt/vttablet/onlineddl/schema.go b/go/vt/vttablet/onlineddl/schema.go
index 0e75aef6ba..f6fc0606ef 100644
--- a/go/vt/vttablet/onlineddl/schema.go
+++ b/go/vt/vttablet/onlineddl/schema.go
@@ -194,7 +194,7 @@ const (
                        migration_status IN ('complete', 'cancelled', 'failed')
                        AND cleanup_timestamp IS NULL
                        AND retain_artifacts_seconds > 0
-                       AND migration_context=%a
+                       AND migration_context COLLATE utf8mb4_bin=%a
        `
        sqlUpdateForceCutOver = `UPDATE _vt.schema_migrations
                        SET force_cutover=1

it's a simple enough change and I think worth it, even if this still means some inconsistency with existing logic. It's just so much simpler. Let me know if you disagree.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • go/vt/sqlparser/ast_format_fast.go: Language not supported

Copy link
Copy Markdown
Member

@mattlord mattlord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

migration_status IN ('complete', 'cancelled', 'failed')
AND cleanup_timestamp IS NULL
AND retain_artifacts_seconds > 0
AND migration_context COLLATE utf8mb4_bin=%a
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will prevent usage of the index on the migration_context column, and this is an update so it is taking X locks on rows it scans, but that is probably OK. We could alternatively make the column use this collation in the schema.

Copy link
Copy Markdown
Contributor Author

@shlomi-noach shlomi-noach May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I forgot to explain, the index this query uses is:

KEY `cleanup_status_idx` (`cleanup_timestamp`, `migration_status`),

and so migration_context is irrelevant to the index search.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated above comment which was poorly worded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component: Online DDL Online DDL (vitess/native/gh-ost/pt-osc) Component: VTTablet Type: Enhancement Logical improvement (somewhere between a bug and feature)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: ALTER VITESS_MIGRATION … CONTEXT 'ctx': extend context-scoped control to all bulk migration operations

3 participants