Repository navigation
Highlights
-
Autoscaling is on by default. On Aurora, Spirit now sets its thread counts from the instance size in
migrate,moveandsync:Target Thread counts Aurora, 4 or more vCPUs Autoscaling: read, write, checksum and flush pools are sized from the instance and scaled on throttler feedback Aurora, fewer than 4 vCPUs Small-instance mode: 1 read thread, 1 write thread, 1 MiB chunks, flush width 1, nothing scales Not Aurora, or --skip-autoscaling--threads/--write-threadsas configured (unchanged)--enable-experimental-autoscalingis replaced by--skip-autoscaling(#1436). Small-instance mode replaces v0.18.0's low-memory mode. It no longer looks at the buffer pool, so 2-vCPU instances with ample memory (db.r6g.large,db.r7g.large,db.t4g.large) are included (#1438). The Aurora throttlers run either way. By @morgo -
migrateuses the lockless checksum by default. It takes noLOCK TABLESat the start of each pass and holds no long-livedREPEATABLE READsnapshot, so a long checksum no longer grows the InnoDB history list.moveandsyncalready used only this checker.--legacy-checksumselects the previous snapshot checker (#1437). For callers that decide whether to retry a failed checksum,checksum.IsReproducibleis now the single answer, andSingleCheckerno longer reportsErrDifferencesExhaustedfor a run whose repair was never re-read (by @Kiran01bm in #1448). -
Experimental:
migrateon tables with foreign keys, on MySQL 9.7+. MySQL 9.6 moved foreign key enforcement into the SQL layer, so cascaded changes are now written to the binary log.--enable-experimental-foreign-keys(default off) allows altering a child table: any copy-pathALTER,DROP FOREIGN KEY, and renaming a column a foreign key uses. It requires MySQL 9.7+ withinnodb_native_foreign_keys=OFF(the default). These are still refused: tables referenced by another table's foreign key (including self-references),ADD FOREIGN KEYor inlineREFERENCES, andDROP CONSTRAINTof a foreign key._newhas no foreign keys during the copy. They are added under the cutover lock withforeign_key_checks=0, after a probe on empty copies confirms MySQL will not build an index. Force-kill covers sessions blocking on the parent tables.moveandsyncare unchanged. Seedocs/migrate.md. By @morgo in #1431 -
Correctness fixes:
- The final change-feed flush under the cutover lock skipped MySQL warning checks. A truncating or out-of-range value that arrived only in that last batch could be written to
_newright before it became live. Writes under the lock now use the same unsafe-warning policy as every other write, and a warning stops the cutover — #1470 - The privileges check could pass when MySQL would not grant the privileges. MySQL applies one database-level grant row to a schema, so an exact-name grant can shadow a pattern grant. The base set is now required on every matching database-level grant — #1442
- Copies with composite or non-auto-increment keys ignored
--target-chunk-sizeand sized chunks by elapsed time. When writes queued, chunks could shrink to the 10-row minimum — #1469 - A valid migration of a table with
CHECKconstraints was refused whenCREATE TABLE ... LIKErewrote a charset introducer in the copied expression. The source definitions are now restored on the empty copy before theALTER— by @budzeg in #1461 spirit diff/DeclarativeToImperative: a schema that defines the same table twice was silently planned from the second definition, and a case-only rename on alower_case_table_names=1|2server producedCREATE+DROP(by @Kiran01bm in #1449). A repeated column, index or constraint name could panicDiff, return "no change", or emit anALTERMySQL rejects (by @aparajon in #1466). Both cases now return an error.
- The final change-feed flush under the cutover lock skipped MySQL warning checks. A truncating or out-of-range value that arrived only in that last batch could be written to
Upgrade Notes
-
Checkpoint compatibility: complete any in-progress schema changes before upgrading, as the checkpoint format is not guaranteed to be stable between versions.
-
Removed and renamed flags. None has an alias. Passing an old name is a parse error.
v0.18.0 v0.19.0 --enable-experimental-autoscalingRemoved; autoscaling is the default. --skip-autoscalingturns it off.--enable-experimental-lockless-checksumRemoved; lockless is the default. --legacy-checksumselects the snapshot checker.--checksum-yield-timeout--legacy-checksum-yield-timeout(only applies with--legacy-checksum) -
Behaviour changes on Aurora (#1436 #1438):
--threadsand--write-threadsare ignored on Aurora unless you pass--skip-autoscaling. A non-default value logs a warning when it is replaced.- 2-vCPU instances that ran at the configured counts in v0.18.0 (default 4/4, 16 MiB chunks, flush width 8) now run at 1/1, 1 MiB chunks, flush width 1. We expect lower copy throughput on those instance sizes. This has not been measured.
--skip-autoscalingrestores the old behaviour. - Non-Aurora servers are unchanged.
-
Lockless checksum behaviour (#1437): a lossy
ALTER(for example, aUNIQUEindex added to non-unique data) now fails after up to 10 lockless passes instead of 3 snapshot attempts. Each pass re-walks the table, so this failure takes longer on large tables. The error still wrapsErrDifferencesExhausted. The checksum status row readslockless:instead ofexperimental lockless:. -
Stricter checks:
- Privileges: a pattern grant (
app\_%.*) without the full base set, next to an exact-name grant with it, is now refused (#1442). movenow runs the version check at preflight against every source and target (#1458).syncchecks the source's binary log settings (binlog_format=ROW,binlog_row_image=FULL, and others), and now requiresTRIGGERandEVENTon the target schema (#1458).- Cutover: an unsafe warning during the final flush under the lock now stops the cutover (#1470).
- Privileges: a pattern grant (
-
Other behaviour changes:
movecutover retries back off (100ms, doubling, capped at 10s), asmigratealready did. The final error lists every attempt asattempt N: …. The log keymax-retriesis nowmax_retries(#1457).sync: the copy's write ceiling is no longer capped to--max-connections, and repairs run at--write-threads(#1463).spirit lint,spirit diffandspirit fmtconnect the same way as the rest of Spirit (#1456):- TLS defaults to
PREFERRED. Addtls=falseto the DSN for the old behaviour. - The session
time_zoneis+00:00. On a non-UTC server, literalTIMESTAMPdefaults can render differently. spirit fmtruns under Spirit'ssql_mode, soDEFAULT '0000-00-00'is now accepted.- A
--databasevalue containing?or%is no longer misread as driver parameters.
- TLS defaults to
spirit diffreadslower_case_table_namesfrom--source-dsnand matches table names case-insensitively when it is 1 or 2 (#1449).
-
Go 1.26.9 is required to build from source. It fixes 7 standard-library vulnerabilities that govulncheck reports as reachable (#1440).
-
Library API changes (for programs embedding Spirit):
flags.Common.EnableExperimentalAutoscalingis nowSkipAutoscaling. The zero value now means "autoscale", so a caller that set nothing gets autoscaling on Aurora. SetSkipAutoscaling: trueto keep the old behaviour (#1436).Migration.EnableExperimentalLocklessChecksumis nowLegacyChecksum, with the opposite meaning. A caller that setEnableExperimentalLocklessChecksum: falsemust setLegacyChecksum: trueto keep the snapshot checker.ChecksumYieldTimeoutis nowLegacyChecksumYieldTimeout(#1437).- New
flags.Common.ThreadsAreBaseline(programmatic only). It marks yourThreads/WriteThreadsas a baseline for non-Aurora servers, so autoscaling replaces them without logging a warning. A caller whose counts are a real load cap should setSkipAutoscalinginstead (#1439). pkg/migration/checkandpkg/move/checkare merged intopkg/check(#1458):ScopeX→PhaseX.check.ChecksInScope(check.ScopeStatement)→check.Checks(check.Migration, check.PhaseStatement).TargetSchemaObjectsError(ctx, targets, tables)→TargetSchemaObjectsError(ctx, resources).StatementRefusalis unchanged.
- Small-instance mode renames:
Plan.LowMemory→Plan.SmallInstance, and theLowMemory*constants →SmallInstance*.LowMemoryMaxBufferPoolBytes,LowMemoryMaxVCPUsanddbconn.BufferPoolSizeare removed (#1438). - Added:
checksum.IsReproducible(#1448)statement.DiffOptions.LowerCaseTableNames(#1449)throttler.AuroraResult.Close,throttler.BuildAurora,dbconn.MonitorOpener(#1454)runtime.RetryCutover(#1457) andruntime.Lifecycle.Teardown(#1463)dbconn.NewTableLockReferencingandTableLock.ExecUnderLockWithoutForeignKeyChecks(#1431), andTableLock.ExecUnderLockWithWarnings(#1470)utils.DBLevelGrantsCoverSchema(#1442)CompareMySQLVersionsmoves frompkg/testutilstopkg/utils(#1431)
- Removed:
ApplierConfig.ChunkletMaxRowsandChunkletMaxSize. They were never read; batches are fixed at 1,000 rows / 1 MiB (#1468).CopierConfig.DBConfig,CheckerConfig.TargetChunkTime,Copier.StartTime,Copier.GetProgress,NewTrxPool'sconfigparameter,utils.ParseRoleNamesanddbconn.KillTransaction(#1450).copier.StartWriteAutoscaler,concurrency.Request.FitandPlan.Cap(#1463).
Additional Changes
-
movefixes. A sharded move whose later source failed to connect leaked the pools it had already opened (#1453). The reverse window is now the only writer of the checkpoint row once it starts. This is defense in depth for #1239 (#1447). By @morgo -
Runner unification. Code that
migrate,moveandsynceach had their own copy of is now shared:- one check registry (#1458)
- the cutover retry loop (#1457)
- Aurora throttler setup and teardown (#1454)
Closeteardown order and read-bound fitting (#1463)
AGENTS.md no longer has a "not yet unified" list. The remaining differences are recorded as deliberate. By @morgo
-
Refactors. Feed code shared by the binlog and GTID clients now lives on
feedCore(#1455). Dead fields, constants and test-only helpers are removed (#1450). Goroutine, timer, warning and TLS code paths are simplified (#1451). By @morgo -
Tests, docs and dependencies.
- Test de-flaking (#1444 #1446).
- Package READMEs checked against current behaviour (#1467).
- The docs now say the copier writes
INSERT IGNORE, notREPLACE(#1452). - The non-strict
sql_modeis documented: zero dates copy, and out-of-range values (1264) still stop the copy (by @aparajon in #1465). - Dependency bumps (#1464 #1473 #1474).
New Contributors
Full Changelog: v0.18.0...v0.19.0