Move Tables: 1.2 skip-tables and run overall move tables flow except cutover (#8206)#1705
Merged
zacharysierakowski merged 50 commits intoJun 11, 2026
Merged
Conversation
… for move-tables feature
- Replace WriteChangelog bypass TODO with intentional comment explaining the single-chokepoint design decision - Remove demo hack code: simulateMoveTablesCutover(), TmpCutoverFilename field, --target-cutover-filename flag, and file-based cutover polling loop - Downgrade per-chunk/per-event debug logging from Info to Debugf - Fix pre-existing test call-sites for changed function signatures (nil args) - Add tests for all #8206 acceptance criteria: - No ghost or changelog table created in move-tables mode - WriteChangelog is a no-op in move-tables mode - No changelog listener registered on the streamer - Heartbeat goroutine not started - finalCleanup skips drop operations
- Replace WriteChangelog bypass TODO with intentional comment explaining the single-chokepoint design decision - Remove demo hack code: simulateMoveTablesCutover(), TmpCutoverFilename field, --target-cutover-filename flag, and file-based cutover polling loop - Downgrade per-chunk/per-event debug logging from Info to Debugf - Fix pre-existing test call-sites for changed function signatures (nil args) - Fix test teardown to drop changelog table between tests - Add tests for all #8206 acceptance criteria: - No ghost or changelog table created in move-tables mode - WriteChangelog is a no-op in move-tables mode - No changelog listener registered on the streamer - Heartbeat goroutine not started - finalCleanup skips drop operations
- Fix TearDownTest assertion ordering: otherDB drop was missing NoError check after _ghc drop line was inserted - Revert Migrate() log strings to 'ghost table' — the 'target table' wording was a regression affecting standard (non-move-tables) users - Fix ApplyIterationMoveTableCopyQueries test to pass suite.db instead of nil to avoid potential panic on sourceDB.Query()
Explain why TestFinalCleanup, TestInitiateStreaming, and TestNoHeartbeat tests verify the guard predicate rather than calling the full function, and which other tests provide the behavioral proof.
- Remove unused simulateMoveTablesCutover() function (missed in demo hack cleanup) - Fix errorlint: use %w instead of %v in fmt.Errorf (3 sites) - Fix ineffassign: suppress unused err from CREATE DATABASE IF NOT EXISTS - Fix rowserrcheck: check sqlRows.Err() after scan loop in ApplyIterationMoveTableCopyQueries - Fix whitespace: remove trailing newline after ApplierConnectionConfig assignment
- Remove contradictory TODO above WriteChangelog bypass (the comment now explains the bypass is intentional, so the TODO was misleading) - Fix typo: #82066 → #8206 in test comment - Update WriteChangelog doc comment to reflect empty-string return in move-tables mode - Improve test comments: fix flawed reasoning in TestFinalCleanup, clarify TestStreaming tautology, add test-infrastructure note to TestHeartbeat
…nce we add checkpoint table
danieljoos
approved these changes
Jun 11, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
This PR continues productionizing --move-tables mode by wiring the “skip ghost/changelog/heartbeat” behavior into the main migrator/applier flow, adding local docker-based move-tables helper scripts, and updating tests to reflect the new move-tables control paths.
Changes:
- Add
GetTargetDatabaseName()/GetTargetTableName()helpers and thread move-tables-aware naming/connection handling through migrator, inspector, and applier flows. - Disable changelog listener/heartbeat (and other ghost/changelog behaviors) in move-tables mode, and adjust row-copy to read from an explicit source DB when moving across clusters.
- Add local
script/move-tables/*andlocaltests/docker-compose-move-tables.ymlscaffolding plus related tests.
Show a summary per file
| File | Description |
|---|---|
go/logic/applier.go |
Move-tables target DB/table handling, changelog no-op, target-table creation, and row-copy API changes. |
go/logic/migrator.go |
Integrates move-tables streaming/copy flow and gates throttling/heartbeat/changelog usage. |
go/logic/inspect.go |
Makes “original table name” move-tables-aware and factors unique-key selection. |
go/base/context.go |
Adds target DB/table helpers; derives move-tables connection config and applies TLS to it. |
go/cmd/gh-ost/main.go |
Initializes move-tables connection config and reorders connection config setup. |
go/logic/applier_test.go |
Adds/adjusts tests for move-tables skip behavior and new method signatures. |
go/logic/migrator_test.go |
Updates tests to pass the new ReadMigrationRangeValues(nil) signature. |
go/base/context_test.go |
Tests move-tables credential derivation and TLS application. |
script/move-tables/* |
Adds local setup/teardown helpers and mysql client wrappers for move-tables topology. |
localtests/docker-compose-move-tables.yml |
Adds a 2-cluster docker-compose topology for local move-tables runs. |
localtests/move-tables/create.sql |
Seeds a sample table/data set for local move-tables testing. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
go/logic/applier.go:180
- InitDBConnections initializes moveTablesTargetDB twice: the two consecutive
if apl.moveTablesConnectionConfig != nil { ... }blocks are identical. This duplicates DB creation/validation work and can leak extra connections if the first succeeds and the second fails later in the function.
if apl.moveTablesConnectionConfig != nil {
moveTablesURI := apl.moveTablesConnectionConfig.GetDBUri(apl.migrationContext.GetTargetDatabaseName()) + "&multiStatements=true"
if apl.moveTablesTargetDB, _, err = mysql.GetDB(apl.migrationContext.Uuid, moveTablesURI); err != nil {
return err
}
if _, err := base.ValidateConnection(apl.moveTablesTargetDB, apl.moveTablesConnectionConfig, apl.migrationContext, apl.name); err != nil {
return err
}
}
if apl.moveTablesConnectionConfig != nil {
moveTablesURI := apl.moveTablesConnectionConfig.GetDBUri(apl.migrationContext.GetTargetDatabaseName()) + "&multiStatements=true"
if apl.moveTablesTargetDB, _, err = mysql.GetDB(apl.migrationContext.Uuid, moveTablesURI); err != nil {
return err
}
if _, err := base.ValidateConnection(apl.moveTablesTargetDB, apl.moveTablesConnectionConfig, apl.migrationContext, apl.name); err != nil {
return err
}
}
go/logic/applier.go:206
- AcquireMigrationLock connects using
GetDBUri(migrationContext.DatabaseName). In move-tables mode, the applier connection points at the target cluster, andDatabaseNamemay not exist there when--target-databasediffers, causing lock acquisition to fail before the migration can run. UsingGetTargetDatabaseName()here keeps the lock connection consistent with the applier DB selection.
func (apl *Applier) AcquireMigrationLock(ctx context.Context) error {
lockName := buildMigrationLockName(apl.migrationContext.DatabaseName, apl.originalTableName())
// Use a dedicated *sql.DB so the pinned connection does not consume a
// slot in apl.db's small pool (mysql.MaxDBPoolConnections).
lockURI := apl.connectionConfig.GetDBUri(apl.migrationContext.DatabaseName)
lockDB, err := gosql.Open("mysql", lockURI)
if err != nil {
- Files reviewed: 17/17 changed files
- Comments generated: 9
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot's findings
Comments suppressed due to low confidence (1)
go/logic/applier.go:180
- This initializes
moveTablesTargetDBtwice with the same URI, which can leak the first*sql.DBhandle and does redundant connection validation. Remove the duplicated secondif apl.moveTablesConnectionConfig != nil { ... }block (or consolidate into a single initialization path).
if !apl.migrationContext.IsMoveTablesMode() {
// read target table columns from applier
if err := apl.readTableColumns(); err != nil {
return err
}
}
if apl.moveTablesConnectionConfig != nil {
moveTablesURI := apl.moveTablesConnectionConfig.GetDBUri(apl.migrationContext.GetTargetDatabaseName()) + "&multiStatements=true"
if apl.moveTablesTargetDB, _, err = mysql.GetDB(apl.migrationContext.Uuid, moveTablesURI); err != nil {
return err
}
if _, err := base.ValidateConnection(apl.moveTablesTargetDB, apl.moveTablesConnectionConfig, apl.migrationContext, apl.name); err != nil {
return err
}
}
if apl.moveTablesConnectionConfig != nil {
moveTablesURI := apl.moveTablesConnectionConfig.GetDBUri(apl.migrationContext.GetTargetDatabaseName()) + "&multiStatements=true"
if apl.moveTablesTargetDB, _, err = mysql.GetDB(apl.migrationContext.Uuid, moveTablesURI); err != nil {
return err
}
if _, err := base.ValidateConnection(apl.moveTablesTargetDB, apl.moveTablesConnectionConfig, apl.migrationContext, apl.name); err != nil {
return err
}
}
- Files reviewed: 17/17 changed files
- Comments generated: 6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes https://github.com/github/database-infrastructure/issues/8206
Building on the work from @chriskirkland and @womoruyi over in #1700, this PR just takes the code from that branch and patches up the git history so there aren't conflicts against the feature branch for the move-tables effort.
I also took some time to clean up some lingering logging from the demo. And applied some changes to fix up some leftover
TODO(chriskirkland)s 🙂For full PR description, i'm deferring to #1700 because there's already a ton of context there!