Другое

Исправление повреждения данных MySQL после миграции с 5.7 на 8.0

Решение проблем с мусорными данными MySQL после миграции с 5.7 на 8.0. Узнайте, как исправить несоответствия наборов символов, проблемы совместимости с MyISAM и восстановить целостность данных.

MySQL вставляет мусорные данные вместо предоставленных значений после миграции сервера. Недавно я перенёс хостинг с одного cPanel WHM VPS сервера на другой, и теперь при вставке данных в таблицы MySQL с помощью PHP скриптов, MySQL сохраняет значения по умолчанию вместо фактических данных, которые я предоставляю. Проблема, кажется, связана с разницей версий MySQL между серверами (5.7.44 на старом сервере против 8.0.44 на новом). Я установил MYSQL_MODE в пустую строку в конфигурации SQL WHM, но проблема сохраняется. PHP код показывает правильную вставку данных, но каким-то образом MySQL повреждает данные. Кроме того, при вставке новых записей MySQL также перезаписывает существующие записи новыми данными, сохраняя при этом оригинальные метки времени. Как исправить проблему повреждения данных MySQL после миграции сервера? Таблица использует движок MyISAM с кодировкой latin1 и содержит столбцы для данных акций, включая sb (символ акции), open, high, low, close, volume, prev, chang, high5, low5 и sdate (метка времени).

Коррупция данных MySQL после миграции с 5.7 на 8.0

Коррупция данных MySQL после миграции с версии 5.7 на 8.0 часто возникает из-за изменений в наборах символов, проблем совместимости с MyISAM и различий в настройках по умолчанию между версиями. Основными причинами являются переход от latin1 к utf8mb4 в качестве набора символов по умолчанию, изменения правил сортировки (collation) и различия в обработке MyISAM в MySQL 8.0. Для решения этой проблемы необходимо устранить несоответствия в наборах символов, преобразовать таблицы в InnoDB и правильно настроить параметры MySQL 8.0.

Содержание

Понимание основных причин коррупции данных

Коррупция данных, с которой вы сталкиваетесь при миграции MySQL с 5.7 на 8.0, вызвана несколькими фундаментальными изменениями между этими версиями. Наиболее значимой проблемой является изменение набора символов по умолчанию - в MySQL 5.7 по умолчанию использовался latin1, тогда как в MySQL 8.0 по умолчанию используется utf8mb4. Когда ваши данные, закодированные в latin1, обрабатываются с использованием настроек utf8mb4 по умолчанию, они интерпретируются некорректно, что приводит к искажению символов.

Еще одним критическим фактором является обработка таблиц MyISAM. Хотя MyISAM по-прежнему работает в MySQL 8.0, реализация словаря данных изменилась значительно. Согласно документации MySQL 8.0, “Формат файла, который MySQL использует для хранения данных, был тщательно протестирован, но всегда существуют обстоятельства, которые могут привести к повреждению таблиц базы данных.”

Изменения в правилах сортировки (collation) также вносят свой вклад в вашу проблему. В MySQL 8.0 изменилось правило сортировки по умолчанию с latin1_swedish_ci на utf8mb4_0900_ai_ci, что влияет на сравнение и хранение данных. Это может вызывать нарушения уникальных ограничений и проблемы интерпретации данных, как отмечено в руководстве по миграции правил сортировки MySQL.

Проблемы с наборами символов и правилами сортировки между версиями MySQL

Несоответствие наборов символов, вероятно, является основной причиной в вашем сценарии коррупции данных. При миграции с MySQL 5.7 на 8.0 несколько критических значений, связанных с символами, изменились:

  • character_set_server: изменился с latin1 на utf8mb4
  • collation_server: изменился с latin1_swedish_ci на utf8mb4_0900_ai_ci

Это означает, что хотя ваша база данных была разработана для работы с кодировкой latin1, новый сервер MySQL ожидает utf8mb4. Как объясняется на Severalnines, “Привилегированные таблицы в схеме MySQL в MySQL 8.0 перемещены в InnoDB. Вы можете создать таблицу engine=MyISAM, и она будет работать как раньше, но копирование таблицы MyISAM в работающий сервер MySQL не сработает, потому что она не будет обнаружена.”

Конкретная проблема с данными акций, такими как символ евро (€) и другие специальные символы, особенно проблематична. Согласно отчетам на Stack Overflow, “Единственное, что кажется помогает - это выполнение команды SET NAMES latin1. После этого мы получаем большинство данных, но некоторые символы, такие как символ евро (€) и другие символы с разных языков, не хранятся правильно в БД.”


Важное замечание: Изменение правила сортировки с latin1_swedish_ci на utf8mb4_0900_ai_ci может нарушать уникальные ограничения, поскольку в новом правиле сортировки ‘a’=‘å’=‘ä’ и ‘o’=‘ö’, что не было в старом правиле сортировки.

Проблемы с движком MyISAM в MySQL 8.0

Таблицы MyISAM особенно уязвимы в MySQL 8.0 из-за нескольких изменений в том, как обрабатывается этот движок. Хотя MyISAM по-прежнему поддерживается, он устарел (deprecated) и известен проблемами с коррупцией. Согласно документации MySQL, “Вы можете проверить состояние таблицы MyISAM с помощью оператора CHECK TABLE, и восстановить поврежденную таблицу MyISAM с помощью REPAIR TABLE.”

Ваша конкретная проблема, при которой существующие записи перезаписываются, но сохраняются временные метки, указывает на проблему коррупции MyISAM. Такое поведение задокументировано в отчетах об ошибках MySQL, где “поврежденная таблица myisam вызывает сбой сервера даже после восстановления” и “Открытие определенных таблиц с разными определениями в .MYI и .frm может привести к сбою сервера.”

Движок хранения MyISAM известен следующими проблемами:

  1. Коррупция файла данных (.MYD файлы)
  2. Коррупция индексов (.MYI файлы)
  3. Несоответствия заголовков между .frm и .MYI файлами

Учитывая вашу таблицу с данными акций, содержащую числовые значения и временные метки, обработка этих типов данных MyISAM может вызывать поведение перезаписи, которое вы наблюдаете.

Диагностика конкретной коррупции данных

Для правильной диагностики вашей проблемы необходимо проверить несколько аспектов вашей базы данных:

1. Конфигурация набора символов

sql
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

2. Анализ структуры таблицы

sql
SHOW CREATE TABLE ваша_таблица_акций;

3. Проверка коррупции данных

sql
CHECK TABLE ваша_таблица_акций;

4. Состояние таблицы MyISAM

sql
SHOW TABLE STATUS LIKE 'ваша_таблица_акций'\G

Если в выводе вы видите “Table is marked as crashed” (Таблица помечена как аварийно завершенная) или “Data corruption detected” (Обнаружена коррупция данных), это подтверждает проблему коррупции MyISAM.

Проблема, которую вы описываете, при которой PHP показывает правильное вставку данных, но MySQL хранит мусорные значения, в сочетании с поведением перезаписи, strongly указывает на несоответствие кодировки символов, вызывающее отправку данных приложением в одном формате, в то время как MySQL ожидает другой формат.

Пошаговые решения

Решение 1: Исправление несоответствия набора символов

  1. Установите правильный набор символов в my.cnf:
ini
[mysqld]
character_set_server=latin1
collation_server=latin1_swedish_ci
  1. Перезапустите службу MySQL после внесения этих изменений.

  2. Проверьте, что настройки применились:

sql
SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'collation_server';

Решение 2: Преобразование MyISAM в InnoDB

MyISAM устарел и подвержен коррупции. Преобразуйте ваши таблицы в InnoDB:

  1. Сделайте резервную копию базы данных:
bash
mysqldump -u имя_пользователя -p имя_базы_данных > backup.sql
  1. Преобразуйте движок таблицы:
sql
ALTER TABLE ваша_таблица_акций ENGINE=InnoDB;
ALTER TABLE ваша_таблица_акций CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
  1. Проверьте преобразование:
sql
SHOW CREATE TABLE ваша_таблица_акций;

Решение 3: Исправление коррупции данных

Если коррупция уже произошла:

  1. Восстановите таблицу:
sql
REPAIR TABLE ваша_таблица_акций;
  1. Если восстановление не удалось, используйте myisamchk (когда MySQL остановлен):
bash
myisamchk -r /var/lib/mysql/ваша_база_данных/ваша_таблица_акций.MYI
  1. При серьезной коррупции восстановите из резервной копии и повторите недавние изменения.

Решение 4: Исправление набора символов подключения PHP

Убедитесь, что ваши PHP-скрипты правильно устанавливают набор символов:

php
<?php
$mysqli = new mysqli("localhost", "имя_пользователя", "пароль", "база_данных");
$mysqli->set_charset("latin1");
?>

Или используйте SET NAMES latin1 в вашем подключении к MySQL:

php
<?php
$mysqli->query("SET NAMES latin1");
?>

Решение 5: Устранение проблем конкретных столбцов

Для вашей таблицы с данными акций, содержащей числовые столбцы, убедитесь в правильности типов данных:

sql
ALTER TABLE ваша_таблица_акций 
MODIFY COLUMN open DECIMAL(10,2),
MODIFY COLUMN high DECIMAL(10,2),
MODIFY COLUMN low DECIMAL(10,2),
MODIFY COLUMN close DECIMAL(10,2),
MODIFY COLUMN volume BIGINT,
MODIFY COLUMN prev DECIMAL(10,2),
MODIFY COLUMN chang DECIMAL(10,2),
MODIFY COLUMN high5 DECIMAL(10,2),
MODIFY COLUMN low5 DECIMAL(10,2);

Профилактические меры для будущих миграций

Чтобы предотвратить эти проблемы в будущих миграциях:

  1. Планируйте миграцию набора символов должным образом:

    • Преобразуйте в utf8mb4 перед обновлением
    • Тщательно протестируйте в промежуточной среде
  2. Избегайте MyISAM для новых установок:

    • Используйте исключительно InnoDB
    • MyISAM устарел и не поддерживается в будущих версиях MySQL
  3. Документируйте схему вашей базы данных:

    • Записывайте наборы символов и правила сортировки для каждой таблицы
    • Указывайте типы движков и их назначение
  4. Используйте правильные инструменты миграции:

    • Используйте mysqldump с явными опциями набора символов
    • Рассмотрите использование мастера миграции MySQL Workbench
  5. Тщательно тестируйте:

    • Тестируйте всю функциональность приложения после миграции
    • Проверяйте целостность данных с помощью контрольных сумм
  6. Мониторьте проблемы:

    • Настройте мониторинг ошибок MySQL
    • Регулярно выполняйте команды CHECK TABLE для критических таблиц

Согласно официальному руководству по миграции MySQL, “Значение по умолчанию для системных переменных character_set_server и character_set_database изменилось с latin1 на utf8mb4.” Понимание этих изменений по умолчанию критически важно для успешных миграций.

Источники

  1. Руководство MySQL 8.0 - Поврежденные таблицы MyISAM
  2. Руководство MySQL 8.0 - Проблемы с таблицами MyISAM
  3. Переход с MySQL 5.7 на MySQL 8.0 - Что вы должны знать
  4. Правила сортировки MySQL 8.0: Миграция со старых правил сортировки
  5. Примечания к выпуску MySQL 8.0 - Изменения в MySQL 8.0.1
  6. Ошибка MySQL #97168 - Обновление с 5.7 на 8.0 не удается: “Обновление словаря данных с MySQL 5.7 в процессе”
  7. Проблема при миграции данных в кодировке latin1 из MySQL 5.7 в 8.0
  8. Руководство MySQL 8.0 - Восстановление после сбоя MyISAM

Заключение

Коррупция данных MySQL, с которой вы сталкиваетесь после миграции с 5.7 на 8.0, в основном вызвана несоответствиями в наборах символов и проблемами совместимости с MyISAM. Для решения этой проблемы:

  1. Исправьте настройки набора символов по умолчанию, установив character_set_server=latin1 и collation_server=latin1_swedish_ci в вашем my.cnf
  2. Преобразуйте таблицы MyISAM в InnoDB для лучшей совместимости и надежности
  3. Восстановите поврежденные таблицы с помощью REPAIR TABLE или myisamchk
  4. Обновите настройки подключения PHP для использования SET NAMES latin1
  5. Правильно определите типы данных столбцов для ваших данных акций

Для будущих миграций тщательно планируйте преобразование набора символов, полностью избегайте MyISAM и тщательно тестируйте в промежуточной среде перед развертыванием в продакшене. Ключевой урок заключается в том, что обновления версий MySQL требуют тщательного внимания к наборам символов, движкам хранения и изменениям конфигурации между версиями.

Авторы
Проверено модерацией
Модерация