Skip to content

Powered by Grav

Percona versions & verifying a migration

Percona versions & verifying a migration

Two things decide how a cross-host move behaves in practice: the Percona version on each end, and how carefully you verify the result. This page covers both — the version-specific behaviour of xoct and xmass, the maintenance pause that keeps the MySQL watchdog from racing a controlled move, and the before/after checklist that lets you trust a migration instead of hoping.

For the mechanics of each tool, start with Cross-host migration and Site import & export; for the Percona 8 upgrade itself, see Percona 8 readiness.

Which tool crosses versions

The transport each tool uses decides whether it can bridge a version gap.

  • xoct exports a logical dump with mydumper on the source and loads it with myloader on the target. A logical dump is portable, so xoct is cross-version safe — a Percona 5.7 account migrates cleanly onto a Percona 8.4 box. This is the tool that performs the actual version jump.
  • xmass takes a physical xtrabackup snapshot and brings the target up as a GTID replica of the source. Physical backup plus replication require identical Percona versions on both ends, so xmass init refuses a mismatch before it touches any data. xmass evacuates a whole box within a version; it does not upgrade one.

The result is a clear adoption path onto Percona 8: upgrade a target box to Percona 8 first, then use xoct to migrate accounts onto it from the older 5.7 boxes. Once a whole region is on 8.4, xmass can evacuate boxes wholesale within that version. The 5.7→8.4 upgrade itself runs in two steps — the strict upgrade path clamps a direct 5.7→8.4 request to 8.0 first — so a box reaches 8.4 through one 5.7→8.0 run and one 8.0→8.4 run.

The MySQL watchdog is paused during a move

BOA runs a MySQL watchdog from cron that keeps a production server alive: if mysqld looks down it restarts it, if a table looks stuck it breaks the lock, and it kills queries that run too long. During everyday operation that is exactly right. During a deliberate database operation it is a hazard — the watchdog cannot distinguish a genuine hang from a controlled FLUSH TABLES WITH READ LOCK at cutover, a slow innodb_fast_shutdown=0 package upgrade, or an in-progress xtrabackup snapshot, and "healing" any of those mid-flight can lose data.

BOA resolves this with a single maintenance marker, /run/boa_sql_maintenance.pid. While the marker is present the watchdog stands down completely — it exits before running any check, so it never restarts, lock-breaks, or query-kills a server that is under deliberate maintenance. The operations that need the pause set the marker around their own critical section and clear it afterwards:

  • a Percona package upgrade holds it across the whole apt transaction and the clean-shutdown restart;
  • xmass holds it on both hosts across init (the source snapshot and the target restore and replica bring-up) and across the whole cutover — the read-lock window at cutover is the single highest-risk moment in the toolchain;
  • xoct holds it for export and import (the myloader load plus the in-place host rename's dump and reimport).

Two safeguards keep the pause from ever becoming a foot-gun. A marker older than four hours is treated as abandoned — left behind by an operation that died without cleaning up — so the watchdog removes it and resumes normal healing rather than staying muted forever; and because the marker lives on a memory-backed filesystem, a reboot clears it too. In normal operation you never touch the marker by hand, and the one operational rule is simple: during a migration or a Percona upgrade, do not force the watchdog to run expecting it to help — it is muted on purpose. The single exception is a hard recovery — if a migration or Percona upgrade dies mid-flight and you are cleaning up by hand, confirm the marker is gone (ls /run/boa_sql_maintenance.pid) before you rely on the watchdog again; the four-hour auto-abandonment clears a stale one regardless, so it never mutes auto-heal for good. See Process guards for the watchdog itself.

What xmass adapts to on Percona 8

Whole-server replication changed substantially between 5.7 and 8.x. xmass is version-aware and adapts automatically; the details are here so the behaviour is understood, not so you configure anything.

  • xtrabackup build and repositories. Physical backup needs the xtrabackup build that matches the server — the -24 build for 5.7, -80 for 8.0, and the -84-lts build for 8.4. BOA's base install configures only the Percona server repository, so xmass enables the matching backup repository (reusing the server repository's keyring and release codename) before installing. It also enables Percona's tools repository, because xtrabackup depends on a Perl MySQL driver whose Debian build pulls a MariaDB client library that BOA keeps uninstallable; the Percona tools build of that driver depends on the Percona client instead and resolves cleanly.
  • Binlog expiry. The older expire_logs_days setting was removed in 8.4, so on 8.0 and later xmass writes the seconds-based equivalent.
  • Replication vocabulary. The MASTER/SLAVE statement family (CHANGE MASTER TO, START SLAVE, SHOW SLAVE STATUS, and the rest) was removed in 8.4 in favour of the SOURCE/REPLICA vocabulary. xmass selects the correct dialect for the running version in every phase — setup, sync, status and cutover — not only at setup time.
  • GTID persistence. Turning GTID on at runtime is not enough: the restore restarts the server, and an unpersisted setting reverts on restart and silently breaks the replica. xmass writes the GTID settings into the include directory the server's configuration actually reads, and confirms GTID is on after the restart.
  • Replica authentication. The default 8.0+ authentication plugin refuses a replica login over a plain (non-TLS) channel unless the replica is told to fetch the source's public key first. xmass sets that option on the replication link and confirms both replica threads are running before it continues.

None of this applies to a same-version 5.7→5.7 move, which uses the -24 xtrabackup build and the legacy vocabulary throughout. The whole cluster of 8.x requirements only appears once both ends are genuinely on Percona 8.

Cache state after a cross-version move

A migrated-in site can arrive carrying the source box's stale object cache and, on Drupal 8 and later, a stale service container. BOA does not attempt a per-site cache rebuild on import — outside the front-end's bootstrap context that rebuild is unreliable on modern Drupal. Instead both xoct import and xmass post-mig flush hard at the infrastructure level: the object-cache service is cold-restarted to drop its contents, and every PHP-FPM master is restarted to drop opcode and APCu caches. This is the treatment BOA trusts against cache and container poisoning after a move.

The visible consequence is that sites are briefly unavailable — a few seconds — immediately after the flush, and warm up on the next request. That is expected, not a fault. Each site's PHP-version pin is preserved separately across the move, so a site stays on its own PHP version rather than falling back to the target account's default.

Verifying a migration

A site returning 200 proves surprisingly little on its own — it can be the front-end catch-all, a page cached from the source, or the wrong account's pool answering. Verification means recording a real baseline on the source and checking the same facts on the target, fetched directly to the target.

Before the move, capture per site: a unique marker string in the page body; a 200 on a real application route rather than the front page; a known row count in a table you can re-count; and a clean drush bootstrap.

After the move, confirm each of these against the target directly:

Check What it proves
the served page contains the exact baseline marker the right content is live — not a cache or a catch-all
200 on the same real route, direct to the target the correct account's pool is executing, not a 403/503
the marker table's row count matches the baseline the database imported completely
drush bootstraps against the target settings, credentials and paths rewrote correctly
the file store's contents are present on the target files transferred
site-level files/private are still symlinks the storage layout survived the move
the source serves the same marker through its proxy the source→target proxy hop is live for the DNS window

A whole-server xmass move adds a few gates of its own: init confirms the version match; both replica threads run with lag falling to zero; each sync reaches a clean dry-run before you run it live; status shows lag under a minute before cutover; and after cutover every account serves its marker on the target, replication is torn down so the target stands alone, and the old box has become a proxy.

The cross-version refusal is itself a gate worth checking deliberately: pointing xmass from a 5.7 source at an 8.4 target must stop at the version check, before any snapshot or replication step, and leave the target untouched. That refusal is the correct outcome — crossing versions is xoct's job.

Field-validated

The behaviour on this page was validated end-to-end on Devuan Daedalus servers across the full version matrix: single-account and whole-server moves at 5.7→5.7, single-account 5.7→8.4 and 8.4→8.4, whole-server 8.4→8.4, and the 5.7→8.4 whole-server refusal. Each target account carried a Drupal 7 site on PHP 7.4 and a Drupal 10 site on PHP 8.4 with page and database markers, and the Percona 8 boxes reached 8.4 through the real two-step upgrade. The version-aware xmass behaviour and the watchdog pause described above were driven into the shipped tools by that campaign.

© 2026 BOA Documentation. All rights reserved.