Миграция MySQL-PXC в MySQL-MGR
Это руководство содержит подробные инструкции по миграции с MySQL-PXC (Percona XtraDB Cluster) 5.7 на MySQL Group Replication (MGR) 8.0 в Alauda Container Platform.
Контекст
Проблема
Срок поддержки MySQL 5.7 закончился в октябре 2023 года, а MySQL-PXC считается устаревшим и удаляется начиная с Alauda Database Service for MySQL v4.3.0. Организациям необходимо перейти на MySQL 8.0, чтобы продолжать получать обновления безопасности и использовать новые возможности.
Миграция рабочих баз данных требует учета множества факторов:
- Совместимость схемы с зарезервированными ключевыми словами MySQL 8.0
- Изменения набора символов (utf8mb4)
- Обновления authentication plugin
- Обеспечение целостности данных во время миграции
Решение
Это руководство содержит подробные, проверенные инструкции по миграции MySQL-PXC 5.7 в MySQL-MGR 8.0:
- Проверенный подход: подтвержден на ACP v4.0+ с использованием Alauda Database Service for MySQL
- Полное покрытие объектов: мигрируются все стандартные объекты MySQL (tables, views, routines, triggers, events, users, grants)
- Совместимость схемы: автоматические проверки и исправления для проблем совместимости с MySQL 8.0
- Комплексная проверка: проверка по 9 категориям объектов
- Минимальный риск: подробные процедуры отката и проверка на каждом этапе
Информация об окружении
PXC vs MGR: ключевые различия
WARNING
Всегда проверяйте фактические имена pod с помощью kubectl get pod -n <namespace> перед выполнением команд миграции.
Типовые сценарии использования
Предварительные требования
Перед выполнением миграции убедитесь, что у вас есть:
- ACP v4.0 или более поздняя версия с MySQL Operator v4.0 или более поздней версии
- Исправно работающий кластер MySQL-PXC 5.7 в качестве источника
- Включенный GTID mode (
@@gtid_mode = ON, @@enforce_gtid_consistency = ON)
- Новый кластер MySQL-MGR 8.0, созданный в качестве цели до начала миграции
- Вместимость хранилища в 2-3 раза больше размера исходной базы данных
- Сетевое подключение с локальной машины к обоим кластерам
Важные ограничения
- Во время экспорта и импорта требуется простой приложения, чтобы обеспечить согласованность
- Рекомендуемый максимальный размер базы данных: 200GB (для более крупных баз могут потребоваться альтернативные подходы)
- На исходном кластере должен быть включен GTID
- Целевой кластер должен быть создан до начала миграции
- Производительность хранилища на целевом кластере должна быть не ниже, чем на исходном
Начало работы
1. Получите пароль root MySQL
# For PXC 5.7 source
kubectl get secret <source-name> -n <source-namespace> -o jsonpath='{.data.root}' | base64 -d
# For MGR 8.0 target
kubectl get secret mgr-<target-name>-password -n <target-namespace> -o jsonpath='{.data.root}' | base64 -d
2. Определите имена Pod
# Check source PXC pods
kubectl get pod -n <source-namespace> | grep <source-name>
# Example output: source-pxc-0, source-pxc-1, source-pxc-2
# Check target MGR pods
kubectl get pod -n <target-namespace> | grep <target-name>
# Example output: target-0, target-1, target-2
3. Проверьте состояние кластера
# Check PXC source status
kubectl get mysql <source-name> -n <source-namespace>
# Expected: STATE = ready, PXCSTATE = ready
# Check MGR target status
kubectl get mysql <target-name> -n <target-namespace>
# Expected: All 3 members ready, STATUS = Running
4. Лучшие практики использования kubectl exec
Для PXC 5.7 (источник):
# No container specifier needed for PXC
kubectl exec <source-name>-pxc-0 -n <namespace> -- \
mysql -uroot -p<password> -e "SQL_HERE"
Для MGR 8.0 (цель):
# Always use -c mysql for MGR
kubectl exec <target-name>-0 -n <namespace> -c mysql -- \
mysql -uroot -p<password> -e "SQL_HERE"
TIP
- Всегда используйте порядок параметров:
kubectl exec -n <namespace> <pod-name> -- <command>
- Используйте
-- (двойной дефис) перед командой, чтобы отделить параметры kubectl от самой команды
- Избегайте heredocs (
<<EOF) с kubectl exec — они часто не работают из-за проблем с экранированием в shell
Руководство по выполнению
Шаг 1: Анализ совместимости схемы
Выполните этот анализ за одну неделю до запланированной миграции.
Выполните следующие команды, чтобы выявить проблемы совместимости схемы:
# Check for reserved keyword columns
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
FROM information_schema.COLUMNS
WHERE LOWER(COLUMN_NAME) IN ('rank','groups','function','tables','indexes','procedure','file','process');
"
# Check for ZEROFILL columns
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE COLUMN_TYPE LIKE '%ZEROFILL%';
"
# Check for invalid date defaults
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT
FROM information_schema.COLUMNS
WHERE COLUMN_DEFAULT = '0000-00-00'
OR COLUMN_DEFAULT = '0000-00-00 00:00:00';
"
Исправление проблем схемы
# Fix reserved keyword columns (example)
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
USE db1;
ALTER TABLE users CHANGE COLUMN rank user_rank INT;
"
# Fix ZEROFILL columns
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
USE db1;
ALTER TABLE products MODIFY COLUMN price DECIMAL(10,2);
"
Шаг 2: Анализ набора символов и collation
Проверьте таблицы, не использующие utf8mb4:
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql','performance_schema','sys')
AND TABLE_COLLATION NOT LIKE 'utf8mb4%';
"
Конвертация в utf8mb4
# Convert databases to utf8mb4
for db in ${DATABASES}; do
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "
ALTER DATABASE ${db} CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
"
done
# Convert tables to utf8mb4
for db in ${DATABASES}; do
TABLES=$(kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE';
")
for table in ${TABLES}; do
echo "Converting ${db}.${table}..."
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} ${db} -e "
ALTER TABLE ${table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
"
done
done
WARNING
Для таблиц с длинными индексами VARCHAR/TEXT (>191 characters) может потребоваться скорректировать длину индексов:
ALTER TABLE users DROP INDEX idx_email;
ALTER TABLE users ADD UNIQUE INDEX idx_email (email(191));
Шаг 3: Создайте целевой экземпляр MySQL-MGR 8.0
Создайте целевой экземпляр MySQL-MGR 8.0 незадолго до этапа миграции данных.
Через Web Console:
- Выберите версию MySQL 8.0
- Настройте ресурсы (рекомендуется +10-20% памяти по сравнению с исходным кластером из-за накладных расходов MySQL 8.0)
- Установите размер хранилища в 2-3 раза больше размера исходной базы данных
Через командную строку:
TARGET_NAME="mysql-8-target"
NAMESPACE="your-namespace"
STORAGE_SIZE="500Gi"
cat << EOF | kubectl -n $NAMESPACE apply -f -
apiVersion: middleware.alauda.io/v1
kind: Mysql
metadata:
name: $TARGET_NAME
namespace: $NAMESPACE
labels:
mysql/arch: mgr
spec:
mgr:
enableStorage: true
image: {}
members: 1
monitor:
enable: true
exporter: {}
resources:
server:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "2"
memory: 4Gi
router:
replicas: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 500m
memory: 512Mi
svcRO:
type: ClusterIP
svcRW:
type: ClusterIP
strictSecurityModeEnabled: true
upgradeOption: {}
volumeClaimTemplate:
metadata: {}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: ${STORAGE_SIZE}
storageClassName: dataservice-topolvmsc
status: {}
params:
mysql: {}
router:
DEFAULT:
max_total_connections: "200"
logger:
level: info
upgradeOption:
autoUpgrade: false
crVersion: 4.2.0
version: "8.0"
EOF
Проверьте целевой кластер:
kubectl -n $NAMESPACE get mysql $TARGET_NAME -w
# Expected: STATE = Ready, MGRSTATE = ready
Шаг 4: Миграция данных, пользователей и привилегий
Критично: остановите запись приложения
Приложение должно оставаться остановленным (или строго только для чтения) с этого момента до завершения cutover. Любые данные, записанные в исходную базу после этого шага, будут потеряны.
Процедура:
-
Остановите запись приложения: масштабируйте приложение до нуля реплик:
kubectl scale deployment <app-name> --replicas=0 -n <app-namespace>
-
Определите базы данных для миграции:
# List user databases (DO NOT include: information_schema, mysql, performance_schema, sys)
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "
SELECT SCHEMA_NAME FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema','mysql','performance_schema','sys');
"
-
Экспортируйте и импортируйте данные:
SOURCE_NAME="source"
SOURCE_NAMESPACE="your-namespace"
SOURCE_MYSQL_PASSWORD="source-root-password"
TARGET_NAME="mysql-8-target"
TARGET_NAMESPACE="your-namespace"
TARGET_MYSQL_PASSWORD="target-root-password"
DATABASES="db1 db2 db3"
for db in ${DATABASES}; do
echo "Migrating database: ${db}..."
# Export from PXC source
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysqldump -uroot -p${SOURCE_MYSQL_PASSWORD} \
--single-transaction \
--quick \
--lock-tables=false \
--set-gtid-purged=ON \
--routines \
--events \
--triggers \
--databases ${db} \
| grep -v "SET @@GLOBAL.GTID_PURGED" \
| kubectl exec -i ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD}
echo "Migrated: ${db}"
done
-
Перенесите пользователей и привилегии:
# List non-system users from PXC source
USERS=$(kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "
SELECT CONCAT('''', User, '''@''', Host, '''')
FROM mysql.user
WHERE User NOT IN ('root','mysql.sys','mysql.session','mysql.infoschema',
'monitor','operator','clustercheck','xtrabackup','replication')
AND User NOT LIKE 'mysql.%'
AND Host != 'localhost';
")
# For each user, create user and apply grants on target
for user_host in ${USERS}; do
echo "Migrating user: ${user_host}..."
# Get CREATE USER statement (includes auth plugin and password hash)
CREATEUSER=$(kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "SHOW CREATE USER ${user_host};")
# Create user on target
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "${CREATEUSER};"
# Get GRANT statements from source
GRANTS=$(kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "SHOW GRANTS FOR ${user_host};")
# Apply grants on target
echo "${GRANTS}" | while read grant; do
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "${grant};"
done
done
# Flush privileges on target
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "FLUSH PRIVILEGES;"
TIP
На целевом MySQL 8.0 SHOW CREATE USER сохраняет исходный authentication plugin и хэш пароля, поэтому пользователи смогут входить в систему со своими существующими паролями после миграции. Если вам нужно переключиться на mysql_native_password для совместимости с клиентами, выполните:
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
ALTER USER ${user_host} IDENTIFIED WITH mysql_native_password BY '<password>';
"
Целевой MySQL 8.4
На целевом MySQL 8.4 plugin mysql_native_password не загружается по умолчанию и не может быть включен, поэтому повторное применение определения SHOW CREATE USER из 5.7/8.0 (которое использует mysql_native_password) завершается ошибкой ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded. Для цели на 8.4 создавайте каждого пользователя заново с plugin по умолчанию caching_sha2_password вместо сохранения исходного хэша:
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
CREATE USER ${user_host} IDENTIFIED BY '<password>';
"
# then re-apply the user's GRANTs (collected above)
Для этого необходимо знать пароль каждого пользователя или сбросить его — хэш mysql_native_password нельзя перенести в caching_sha2_password. Убедитесь, что application drivers/connection strings поддерживают caching_sha2_password.
TIP
Указанный выше подход со streaming mysqldump не требует дискового пространства для dump-файлов.
Шаг 5: Проверьте миграцию
TARGET_NAME="mysql-8-target"
TARGET_NAMESPACE="your-namespace"
TARGET_MYSQL_PASSWORD="target-root-password"
DATABASES="db1 db2 db3"
for db in ${DATABASES}; do
echo "=== Verifying database: ${db} ==="
# Compare table counts
echo "Tables:"
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE';"
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE';"
# Verify views execute correctly
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -N -e "
SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '${db}';
" | while read view; do
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} ${db} -e "SELECT 1 FROM ${view} LIMIT 1;" > /dev/null 2>&1 \
&& echo "✓ View ${view} OK" \
|| echo "✗ View ${view} FAILED"
done
done
Контрольный список проверки:
Шаг 6: Постмиграционная оптимизация
1. Обновите статистику таблиц
for db in ${DATABASES}; do
echo "Analyzing tables in ${db}..."
TABLES=$(kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -N -e "
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE';
")
for table in ${TABLES}; do
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} ${db} -e "ANALYZE TABLE ${table};" 2>&1 | grep -v "Table"
done
done
2. Проверьте фрагментацию
# Build properly-quoted comma-separated list
DB_LIST=$(echo $DATABASES | sed "s/ /','/g")
DB_LIST="'$DB_LIST'"
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
SELECT TABLE_SCHEMA, TABLE_NAME,
ROUND(DATA_FREE / 1024 / 1024, 2) AS 'Fragmentation (MB)'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA IN ($DB_LIST)
AND DATA_FREE > 0
ORDER BY DATA_FREE DESC;
"
Если обнаружена значительная фрагментация (>100MB), перестройте таблицы:
OPTIMIZE TABLE db1.orders;
Cutover приложения
Шаг 7: Переключите приложение на целевой кластер
1. Убедитесь, что приложение остановлено
# Ensure application is scaled down
kubectl scale deployment <app-name> --replicas=0 -n <app-namespace>
# Verify no active connections on source
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "SHOW PROCESSLIST;" | grep -v "Sleep"
2. Обновите строку подключения приложения
# Update ConfigMap or environment variables
kubectl patch configmap <app-config> -n <app-namespace> --type=json \
-p='[{"op": "replace", "path": "/data/database-host", "value":"mysql-8-target-read-write.'${TARGET_NAMESPACE}'.svc.cluster.local"}]'
kubectl patch configmap <app-config> -n <app-namespace> --type=json \
-p='[{"op": "replace", "path": "/data/database-port", "value":"3306"}]'
3. Перезапустите приложение
# Scale up application
kubectl scale deployment <app-name> --replicas=<original-replica-count> -n <app-namespace>
# Wait for pods to be ready
kubectl -n <app-namespace> rollout status deployment <app-name>
4. Проверьте работоспособность приложения
# Test database connectivity
kubectl exec <app-pod> -n <app-namespace> -- \
mysql -h mysql-8-target-read-write.${TARGET_NAMESPACE}.svc.cluster.local \
-uroot -p${TARGET_MYSQL_PASSWORD} -e "SELECT 1 AS test;"
# Check application logs for errors
kubectl logs -n <app-namespace> <app-pod> --tail=100 | grep -i error
Мониторинг
Отслеживайте мигрированный экземпляр в течение 24-48 часов:
# Check MySQL 8.0 instance health
kubectl -n ${TARGET_NAMESPACE} get mysql ${TARGET_NAME} -w
# Monitor error logs
kubectl logs -n ${TARGET_NAMESPACE} ${TARGET_NAME}-0 -c mysql --tail=100 -f
Аварийное восстановление
План отката
Если после cutover обнаружены критические проблемы:
# 1. Stop application
kubectl scale deployment <app-name> --replicas=0 -n <app-namespace>
# 2. Update connection string back to source
kubectl patch configmap <app-config> -n <app-namespace> --type=json \
-p='[{"op": "replace", "path": "/data/database-host", "value":"'${SOURCE_NAME}'-proxysql.'${SOURCE_NAMESPACE}'.svc.cluster.local"}]'
# 3. Restart application
kubectl scale deployment <app-name> --replicas=<original-replica-count> -n <app-namespace>
# 4. Verify connectivity
kubectl exec <app-pod> -n <app-namespace> -- \
mysql -h ${SOURCE_NAME}-proxysql.${SOURCE_NAMESPACE}.svc.cluster.local \
-uroot -p${SOURCE_MYSQL_PASSWORD} -e "SELECT 1 AS test;"
WARNING
Не удаляйте custom resources PXC, пока миграция не будет подтверждена и не истечет окно отката.
Частые проблемы и решения
Проблема: ошибка GTID_PURGED
Симптомы:
ERROR 3546 (HY000) at line XX: Cannot update GTID_PURGED with the Group Replication plugin running
Решение: уже учтено в процедуре миграции путем фильтрации с помощью grep -v "SET @@GLOBAL.GTID_PURGED"
Проблема: ошибки преобразования набора символов
Симптомы:
ERROR 1366 (HY000): Incorrect string value
Решение:
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
ALTER DATABASE ${db} CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
"
Проблема: ошибки привилегии DEFINER
Симптомы:
ERROR 1449 (HY000): The user specified as a definer ('user'@'host') does not exist
Решение:
# Find all objects with missing definers
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
SELECT DISTINCT DEFINER
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = '${db}';
"
Проблема: ошибки authentication plugin
Симптомы:
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded
Решение (цель MySQL 8.0): переключите пользователя на mysql_native_password для более старых клиентов, которые не могут согласовать caching_sha2_password:
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
FLUSH PRIVILEGES;
"
Решение (цель MySQL 8.4): mysql_native_password недоступен в 8.4 (ERROR 1524: Plugin 'mysql_native_password' is not loaded), поэтому использовать его как резервный вариант нельзя. Вместо этого обновите client driver/connector до версии, поддерживающей caching_sha2_password (и используйте TLS, который требуется caching_sha2_password для первоначального обмена паролем при подключении не с локального хоста). Оставьте пользователя на plugin по умолчанию caching_sha2_password.
Устранение неполадок
Диагностические команды
Проверка хода миграции:
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -e "SHOW PROCESSLIST;"
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -e "SHOW PROCESSLIST;"
Проверка целостности данных:
for db in ${DATABASES}; do
echo "=== Database: ${db} ==="
kubectl exec ${SOURCE_NAME}-pxc-0 -n ${SOURCE_NAMESPACE} -- \
mysql -uroot -p${SOURCE_MYSQL_PASSWORD} -N -e "
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME;
" > /tmp/source_counts.txt
kubectl exec ${TARGET_NAME}-0 -n ${TARGET_NAMESPACE} -c mysql -- \
mysql -uroot -p${TARGET_MYSQL_PASSWORD} -N -e "
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '${db}' AND TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME;
" > /tmp/target_counts.txt
diff /tmp/source_counts.txt /tmp/target_counts.txt || echo "Row count differences detected!"
done
Проверка журналов ошибок MySQL 8.0:
kubectl logs -n ${TARGET_NAMESPACE} ${TARGET_NAME}-0 -c mysql --tail=100 -f | grep -i error
Рекомендации
Планирование до миграции
- Тестирование в Staging: всегда сначала выполняйте тестовую миграцию вне production
- Очистка схемы: исправьте все проблемы совместимости схемы до миграции production
- Миграция набора символов: заранее переведите на utf8mb4 (за 3-5 дней до миграции)
- Стратегия резервного копирования: убедитесь, что доступны свежие резервные копии
- Окно обслуживания: запланируйте достаточное время простоя в зависимости от размера базы данных
Во время миграции
- Остановите запись приложения: убедитесь, что во время export/import нет записей для сохранения согласованности
- Отслеживайте прогресс: регулярно контролируйте ход export/import
- Сохраняйте исходный кластер: не удаляйте исходный кластер до подтверждения миграции
После миграции
- Комплексное тестирование: тщательно проверьте функциональность приложения
- Мониторинг производительности: отслеживайте производительность запросов в течение 24-48 часов
- Сохраняйте источник для отката: держите исходный кластер доступным 24-48 часов на случай rollback
- Обновите документацию: обновите строки подключения и панели мониторинга
Справка
Оценка размера и времени
Справка по флагам mysqldump
Полезные ссылки