Migrate MySQL-PXC to MySQL-MGR
This guide provides comprehensive instructions for migrating from MySQL-PXC (Percona XtraDB Cluster) 5.7 to MySQL Group Replication (MGR) 8.0 on Alauda Container Platform.
TOC
BackgroundThe ChallengeThe SolutionEnvironment InformationPXC vs MGR: Key DifferencesCommon Use CasesPrerequisitesImportant LimitationsGetting Started1. Set Variables2. Verify Source Status3. Run a Command on the SourceExecution GuideStep 1: Schema Compatibility AnalysisFix Schema IssuesStep 2: Character Set and Collation AnalysisOptional: Convert to utf8mb4Step 3: Create Target MySQL-MGR 8.0 InstanceStep 4: Migrate Data, Users, and PrivilegesStep 5: Verify MigrationStep 6: Post-Migration Optimization1. Update Table Statistics2. Check FragmentationApplication CutoverStep 7: Switch Application to Target1. Verify Application is Stopped2. Update Application Connection String3. Restart Application4. Verify Application FunctionalityMonitoringDisaster RecoveryRollback PlanCommon Issues and SolutionsIssue: GTID_PURGED ErrorIssue: Server has GTIDs disabledIssue: Character Set Conversion ErrorsIssue: Specified key was too longIssue: Case-sensitive values are rejectedIssue: Network Interruption During MigrationIssue: DEFINER Privilege ErrorsIssue: Authentication Plugin ErrorsTroubleshootingDiagnostic CommandsBest PracticesPre-Migration PlanningDuring MigrationPost-MigrationReferenceSize vs Time Estimatesmysqldump Flags ReferenceUseful LinksBackground
The Challenge
MySQL 5.7 reached End of Life (EOL) in October 2023, and MySQL-PXC is deprecated and removed starting from Alauda Database Service for MySQL v4.3.0. Organizations must migrate to MySQL 8.0 to continue receiving security updates and to leverage new features.
Migrating production databases involves complex considerations:
- Schema compatibility with MySQL 8.0 reserved keywords
- Character set and collation review
- Authentication plugin updates
- Ensuring data integrity during migration
The Solution
This guide provides comprehensive, verified instructions for migrating MySQL-PXC 5.7 to MySQL-MGR 8.0:
- Proven Approach: Validated on ACP v4.0+ using Alauda Database Service for MySQL
- Complete Object Coverage: Migrates all standard MySQL objects (tables, views, routines, triggers, events, users, grants)
- Schema Compatibility: Automated checks and fixes for MySQL 8.0 compatibility issues
- Comprehensive Verification: Verification across 9 object categories
- Minimal Risk: Detailed rollback procedures and validation at each step
Environment Information
PXC vs MGR: Key Differences
Always check your actual pod names with kubectl get pod -n <namespace> before running migration commands.
Common Use Cases
Prerequisites
Before performing migration, ensure you have:
- ACP v4.0 or later with MySQL Operator v4.0 or later
- A healthy MySQL-PXC 5.7 cluster as source (GTID is not required on the source;
@@gtid_modemay beOFF) - Permission and capacity to create a new MySQL-MGR 8.0 cluster as the target (Step 3)
- Storage capacity of 2-3x the source database size
- Network connectivity from your local machine to both clusters
Important Limitations
- Application downtime is required during export and import to ensure consistency
- Recommended maximum database size: 200GB (larger databases may require alternative approaches)
- The target cluster must be created before the data export in Step 4
- Storage performance on target should match or exceed the source
Getting Started
1. Set Variables
Every command in this guide uses the variables below. Run them first, and run the rest of the guide in the same terminal. If you open a new terminal, set them again.
Find the name and namespace of your PXC source:
Set the source variables, and choose a name for the target that you will create in Step 3. Replace the example values:
You set TARGET_MYSQL_PASSWORD in Step 3, after the target exists, and DATABASES in Step 4.
2. Verify Source Status
3. Run a Command on the Source
The source takes no container specifier:
The target needs -c mysql, as shown in Step 3.
- Use
--(double dash) before the command to separate kubectl options from the command - Avoid heredocs (
<<EOF) withkubectl exec- they often fail due to shell quoting issues
Execution Guide
Step 1: Schema Compatibility Analysis
Perform this analysis one week before the planned migration.
Run the following commands to detect schema compatibility issues:
Fix Schema Issues
These are examples. Replace the database, table and column names with the ones the checks found.
Step 2: Character Set and Collation Analysis
Converting to utf8mb4 is optional. The dump keeps each table's character set and collation, so latin1 and utf8 tables can be migrated as they are. Convert only if the application needs utf8mb4, for example to store emoji. Do not convert a database that belongs to a third-party application, such as Nacos, unless its vendor supports the change.
Check for non-utf8mb4 tables:
Keep this output. You need the original collations if you have to revert a conversion.
Optional: Convert to utf8mb4
Before converting, check for these two problems:
- Case-sensitive collations: a
_bincollation treatsApp.yamlandapp.yamlas different values, bututf8mb4_unicode_cidoes not. Converting fails withERROR 1062if both values exist. If they do not, the conversion succeeds and the unique index then rejects values that differ only by case. The commands below skip tables with a_bintable collation. - Long indexes: utf8mb4 uses up to 4 bytes per character, and the index limit is 3072 bytes across all columns of the index (767 bytes per column for the
COMPACTandREDUNDANTrow formats).
This query lists the indexes that would exceed 3072 bytes. It estimates non-character columns at 8 bytes each:
A table listed by this query fails to convert with ERROR 1071. Leave it as it is unless you can shorten its columns. See the "Specified key was too long" issue under Common Issues and Solutions.
To convert, list only the databases you have decided to convert. ALTER TABLE rebuilds each table, and on PXC it blocks writes across the cluster by default while it runs, so use a maintenance window.
These commands continue after a table fails, so read the output for FAILED lines. A failed table is unchanged, and the tables around it may already be converted.
Step 3: Create Target MySQL-MGR 8.0 Instance
Create the target MySQL-MGR 8.0 instance shortly before the data migration phase.
Using Web Console:
- Select MySQL version 8.0
- Configure resources (recommend +10-20% memory over source cluster due to MySQL 8.0 overhead)
- Set storage size to 2-3x source database size
Using Command Line:
Verify target cluster:
Set the target password:
Step 4: Migrate Data, Users, and Privileges
The application must remain stopped (or strictly read-only) from this point until the cutover is complete. Any data written to the source database after this step will be lost.
Procedure:
-
Stop Application Writes: Scale the application to zero replicas:
-
Identify Databases to Migrate:
Set
DATABASESto the ones you are migrating, separated by spaces: -
Export and Import Data:
If any database prints
FAILED, read the error above it and fix the problem before you continue.Migratedonly means that the commands reported no error. A broken connection can still leave a table short of rows, so Step 5 compares the data.Keep set-gtid-purged OFFDo not change this flag to
ONorAUTO:- On a source with
@@gtid_mode = OFF(common on legacy PXC instances),--set-gtid-purged=ONmakesmysqldumpprintError: Server has GTIDs disabled.and still exit with status 0. A 5.7mysqldumpprints it after exporting the data, so the import is complete despite the message. An 8.0mysqldumpprints it before any data, so nothing is imported while the pipeline reports no failure and the loop printsMigrated. Either way, a clean run of the loop does not prove that data was migrated. - On a source with GTID enabled,
ON/AUTOprependSET @@SESSION.SQL_LOG_BIN= 0;to the dump. Applied on the MGR primary, that keeps the whole import out of the binary log, so the other group members never receive the data. All members still showONLINE, and the first later write to that data makes the secondaries fail and leave the group. The operator may then rebuild them by clone from the primary, which also copies any other data that exists only on the primary.
This migration is a logical dump and restore with no replication channel, so the source's GTID state is not needed on the target.
- On a source with
-
Migrate Users and Privileges:
TIPSHOW CREATE USERpreserves the original authentication plugin and password hash, so users can log in with their existing passwords after migration. If you need to switch tomysql_native_passwordfor client compatibility, run:
The mysqldump streaming approach above does not require disk space for dump files.
Step 5: Verify Migration
Compare row counts on every member. A broken connection can leave a table short of rows without any error, so check every table:
Every table should print OK on every member. A member may briefly lag behind, so run the comparison again before you act on a single MISMATCH.
- Low or missing on every member: the import did not finish. See "Network Interruption During Migration" under Common Issues and Solutions.
- Present on the primary but missing on a secondary: the import was applied with binary logging disabled (see the warning under Step 4). Keep the application stopped and re-run the import with
--set-gtid-purged=OFF, which repairs the secondaries as long as nothing has written to that data yet. After such a write the secondaries leave the group. Check whether the operator has rebuilt them: all membersONLINEwith matching counts. If not, recreate the target instance and repeat the migration.
Verification Checklist:
- Same number of tables in each database
- Same row counts per table on every member
- Same number of views
- All views execute successfully
- All stored procedures and functions exist
- All triggers and events migrated
- All user accounts exist
- All grants migrated
Step 6: Post-Migration Optimization
1. Update Table Statistics
2. Check Fragmentation
If significant fragmentation found (>100MB), rebuild tables:
Application Cutover
Step 7: Switch Application to Target
1. Verify Application is Stopped
2. Update Application Connection String
3. Restart Application
4. Verify Application Functionality
Monitoring
Monitor the migrated instance for 24-48 hours:
Disaster Recovery
Rollback Plan
If critical issues are discovered after the cutover:
Do not delete PXC custom resources until migration is verified and rollback window has passed.
Common Issues and Solutions
These commands use the variables from Getting Started. Where a command uses ${db} or ${table}, first set them to the affected database and table, for example db="db1".
Issue: GTID_PURGED Error
Symptoms:
Solution: The dump was produced with --set-gtid-purged=ON or AUTO. Re-run the export with --set-gtid-purged=OFF as shown in Step 4, which emits no GTID_PURGED statement.
Issue: Server has GTIDs disabled
Symptoms:
mysqldump still exits with status 0. With a 5.7 mysqldump the message appears after the data has been exported and the import is complete. With an 8.0 mysqldump the dump contains no data, so this message may be the only sign of the failure. Check the target to see which applies.
Solution: The source has @@gtid_mode = OFF and the dump was started with --set-gtid-purged=ON. Use --set-gtid-purged=OFF as shown in Step 4. Do not enable GTID on the source for this migration; it is not needed.
Issue: Character Set Conversion Errors
Symptoms:
Solution:
Issue: Specified key was too long
Symptoms:
Solution: The table has an index that does not fit in utf8mb4. The table is unchanged and can be migrated as it is, so the simplest fix is not to convert it. If the database belongs to a third-party application, such as older Nacos schemas with the config_info_aggr table, also revert any of its tables that were already converted. See the "Case-sensitive values are rejected" issue below.
If the table must use utf8mb4, first check that the data fits in shorter columns with SELECT MAX(CHAR_LENGTH(column_name)) FROM table_name;, then reduce the column lengths and convert again. Do not shorten a UNIQUE index with a prefix such as column_name(191), because values that differ only after the prefix then count as duplicates.
Issue: Case-sensitive values are rejected
Symptoms:
The error appears during CONVERT TO, or afterwards when the application writes a value that differs from an existing one only by case.
Solution: The table had a case-sensitive _bin collation and was converted to utf8mb4_unicode_ci. Convert it back to the original character set and collation from the Step 2 output, and restore the database default. Replace utf8 and utf8_bin if the originals were different:
Any 4-byte characters written since the conversion do not fit in utf8, so check for them and take a backup first. TEXT columns remain MEDIUMTEXT after the revert, which is harmless.
Issue: Network Interruption During Migration
Symptoms: The connection drops during Step 4, the loop prints FAILED, or Step 5 prints MISMATCH.
A broken stream can look like a successful import. If the stream stops between statements, or at a point that still forms valid SQL, mysql exits with status 0 and the table is missing or short of rows. Always run the row count comparison in Step 5, even if every database printed Migrated.
Solution, before the application writes to the target:
- Keep the application stopped, so the source does not change.
- When the network is back, check that the source is healthy and that all target members are
ONLINE: The primary may have changed. The commands in this guide import through${TARGET_NAME}-0, so if it is no longer the primary, use the pod that is. - Set
DATABASESto the databases that did not finish or that Step 5 reported, then re-run the export and import loop in Step 4. You do not need to drop anything first, because the dump drops and recreates each table, view, routine and event that it contains. - Run Step 5 again. Continue only when every table prints
OK.
If the interruption happened while migrating users, re-run that step as well. ERROR 1396 for a user that already exists is expected, but confirm that the other users and all grants are present.
If the interruption happened during a schema fix or a utf8mb4 conversion on the source, check the state of that table and re-run the statement if it did not apply.
Solution, after the application has written to the target:
Do not re-run the dump, because it replaces the tables and removes those writes. Fix the network and continue on the target, or follow the Rollback Plan under Disaster Recovery. Rolling back loses anything written to the target since the cutover.
To reduce the risk:
- Run the migration from a host close to the cluster, inside
tmuxorscreen, so that a dropped session does not stop it. - Rehearse in staging to learn how long the stream runs. A proxy or load balancer in front of the Kubernetes API server may close long
kubectl execsessions. - For large databases, list one database in
DATABASESat a time, so that a failure costs less to repeat.
Issue: DEFINER Privilege Errors
Symptoms:
Solution:
Issue: Authentication Plugin Errors
Symptoms:
Solution:
Troubleshooting
Diagnostic Commands
Check Migration Progress:
Verify Data Integrity:
Use the row count comparison in Step 5. Do not compare TABLE_ROWS from information_schema.TABLES, because it is only an estimate for InnoDB tables.
Check MySQL 8.0 Error Logs:
Best Practices
Pre-Migration Planning
- Test in Staging: Always perform a test migration in non-production first
- Schema Cleanup: Fix all schema compatibility issues before production migration
- Character Set Migration: If you choose to convert to utf8mb4, do it well in advance (3-5 days before). Do not convert third-party application databases
- Backup Strategy: Ensure recent backups are available before migration
- Maintenance Window: Schedule adequate downtime based on database size
During Migration
- Stop Application Writes: Ensure no writes during export/import for consistency
- Monitor Progress: Track export/import progress at regular intervals
- Keep Source Running: Don't delete source until migration is verified
Post-Migration
- Comprehensive Testing: Thoroughly test application functionality
- Performance Monitoring: Monitor query performance for 24-48 hours
- Keep Source for Rollback: Maintain source cluster for 24-48 hours for rollback window
- Update Documentation: Update connection strings and monitoring dashboards