Практический опыт обновления MySQL 5.7 до версии 8.0

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

image

Недавно мы обновили свои сервера с MySQL 5.7 на 8.0.

Оставим за рамками этой статьи зачем и какие новые плюшки появились в MySQL 8.0, а вместо этого расскажем о том, с какими сложностями мы столкнулись в процессе обновления.

Во-первых, перед обновлением стоит посмотреть на список изменений и поправить свой конфиг-файл.

Как минимум, удалены следующие параметры:
innodb_file_format, innodb_file_format_check, innodb_file_format_max,innodb_large_prefix
query_cache_limit, query_cache_min_res_unit, query_cache_size, query_cache_type, query_cache_wlock_invalidate.

В параметре sql_mode удалён в частности NO_AUTO_CREATE_USER — что особенно важно, т.к. в MySQL 5.7 он был включен по-умолчанию.

Инструкция по in-place upgrade есть у Percona. И в общем случае можно следовать ей, однако нам удалось так обновить только один кластер, у остальных попытка такого обновления заканчивалась неудачно с подобной ошибкой:

2019-06-22T05:04:18.510888Z 1 [ERROR] [MY-011014] [Server] Found partially upgraded DD. Aborting upgrade and deleting all DD tables. Start the upgrade process again.
2019-06-22T05:04:23.115018Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2019-06-22T05:04:23.115655Z 0 [ERROR] [MY-010119] [Server] Aborting

Поэтому остальные кластеры мы обновляли путем поднятия нового пустого инстанса и восстановления дампа БД с предыдущей версии.

Чтобы сделать такое, во-первых, потребуется дамп БД. И тут поджидает опасность #1 — сделанный стандартным образом дамп:

mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events > dump.sql

не восстанавливается, выдавая ошибку:

ERROR 3554 (HY000) at line 15915: Access to system table 'mysql.innodb_index_stats' is rejected.

Описание есть в багтрекере MySQL (со статусом Not a bug :), там же есть и совет как делать дамп, чтобы его таки можно было восстановить:

mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats > dump.sql

Но при попытке использовать такой дамп, если в нём присутствовали триггеры (а у нас они были), может поджидать опасность #2, в виде вот такой ошибки:

ERROR 1231 (42000) at line 54: Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'

Причина этого в том, как MySQL использует sql_mode для триггеров, а именно: MySQL сохраняет значение sql_mode для триггера в момент его создания и выполняет его потом всегда с этим значением. И соответственно сохраняет это значение в дамп.

Описание этого в справке:
dev.mysql.com/doc/refman/8.0/en/create-trigger.html
MySQL stores the sql_mode system variable setting in effect when a trigger is created, and always executes the trigger body with this setting in force, regardless of the current server SQL mode when the trigger begins executing.

Что же нам делать? Мы просто с помощью sed вырезали NO_AUTO_CREATE_USER из готового дампа. Подобной командой:

sed "s/50003 SET sql_mode              = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER/50003 SET sql_mode              = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO/g" dump.sql > dump2.sql

После этого дамп успешно восстанавливается, но нас поджидает опасность #3 (вполне ожидаемая правда) — системные таблицы восстановлены в состоянии от версии 5.7 и в логах у нас следующие ошибки:

[ERROR] [MY-013143] [Server] Column count of mysql.user is wrong. Expected 51, found 45. The table is probably corrupted

По опыту работы с прошлыми версиями это лечится запуском mysql_upgrade — но начиная с версии 8.0.16 — это не работает, т.к. mysql_upgrade объявлен deprecated и ничего не делает.

Теперь, чтобы вызвать обновление системных таблиц, необходимо запустить MySQL с опцией upgrade=FORCE.

На свежей ubuntu это можно сделать следующим образом:

systemctl set-environment MYSQLD_OPTS="--upgrade=FORCE"

После чего перезапустить MySQL. Ну и после успешного обновления удалить её:

systemctl unset-environment MYSQLD_OPTS
Источник: https://habr.com/ru/post/476852/

Интересные статьи

Интересные статьи

Чтобы покрытие кода было достаточным, а создание нового функционала и рефакторинг старого проходили без страха что-то сломать, тесты должны быть поддерживаемыми и легко читаемыми. В...
Ученый работает над вакциной против COVID-19 в Университете Копенгагена. Дания, 23 марта 2020. Всего за 10 дней количество заболевших COVID-19 увеличилось почти вдвое – 153 тысячи 14 марта п...
Всем привет! Меня зовут Анатолий Варивончик. Я работаю в Badoo уже больше года, а мой общий стаж Android-разработки — более пяти лет. В своей практике я и мои коллеги часто сталкиваемся с необ...
В прошлом году, нашей команде повезло принять участие в разработке программного обеспечения для социально значимого проекта – системы ввода архивных данных военных комиссариатов Хабаровского края...
Сегодня мы поговорим о перспективах становления Битрикс-разработчика и об этапах этого пути. Статья не претендует на абсолютную истину, но даёт жизненные ориентиры.