Эта статья была первоначально написана Джеем Янссеном для блога MySQL Performance .
Куда твой план отката?
Обновления MySQL 5.6 идут полным ходом, и важно знать, как безопасно перейти с MySQL 5.5 на 5.6. При обновлении среды репликации важно создать план миграции, который позволяет безопасно выполнить обновление с минимальным риском — откат часто является очень важным компонентом для этого.
Для многих людей это означает модернизацию рабов, а затем и хозяина. Стратегия репликации старого мастера на новый ведомый хорошо известна и очень долго поддерживается в репликации MySQL . Если быть точным: у вас может быть MySQL 5.6 slave-сервера master 5.5, и это должно работать нормально, пока вы не обновите ваш master и / или не повысите статус одного из slave до master.
Тем не менее, есть те из нас, кто любит жить на грани и делать неподдерживаемые вещи. Предположим, что при переходе на этот мастер MySQL 5.6 ваше приложение полностью ломается. Каким будет ваш план отката? В таком случае было бы полезно оставить подчиненный 5.5 нового мастера 5.6 (или, возможно, настройку двойного мастера с 5.5 и 5.6), чтобы можно было выполнить откат, но все еще иметь данные, записанные на мастер 5.6.
Что может сломаться?
С репликацией на основе операторов (SBR) вы, как правило, в порядке с этим типом установки, при условии, что вы не будете выполнять какие-либо действия, связанные с синтаксисом MySQL 5.6, до тех пор, пока у вас не останется больше подчиненных устройств 5.5. Однако с репликацией на основе строк (RBR) все немного сложнее, особенно при изменении форматов столбцов.
Теперь одна приятная новая особенность MySQL 5.6 — это улучшение требований к хранилищу для полей DATETIME, а также добавление поддержки доли секунды для TIME, DATETIME и TIMESTAMP. Это замечательно, но, к сожалению, это новый формат столбцов, который 5.5 явно не поймет. Это ставит под угрозу нашу репликацию от 5,6 до 5,5? Ответ: если мы будем осторожны, НЕТ.
Проще говоря, MySQL 5.6 поддерживает как старые, так и новые типы, а mysql_upgrade не выполняет такое преобразование в существующих таблицах. Только НОВЫЕ таблицы или таблицы REBUILT в 5.6 будут использовать новый формат. Любые таблицы от 5.5 с простым mysql_upgrade до 5.6 будут по-прежнему использовать старые типы. Для получения дополнительной информации о том, как найти столбцы в 5.6, которые используют старый формат, см . Отличный пост в блоге Айка Уокера на эту тему . (Спасибо Айк!)
Несовершенный тест
Чтобы проверить это, я создал простой эксперимент. У меня есть ведущий и ведомый, использующие RBR, оба на 5.5, и я устанавливаю pt-heartbeat для обновления мастера. Я понял, что pt-heartbeat на самом деле использует varchar для поля метки времени — я подозреваю, что это облегчает поддержку нескольких баз данных. Однако, поскольку обновление pt-heartbeat использует NOW () для заполнения этого поля, я могу преобразовать его в DATETIME:
[root@master ~]# pt-heartbeat --update --database percona --create-table CREATE TABLE `heartbeat` ( `ts` varchar(26) NOT NULL, `server_id` int(10) unsigned NOT NULL, `file` varchar(255) DEFAULT NULL, `position` bigint(20) unsigned DEFAULT NULL, `relay_master_log_file` varchar(255) DEFAULT NULL, `exec_master_log_pos` bigint(20) unsigned DEFAULT NULL, PRIMARY KEY (`server_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 master mysql> alter table heartbeat drop column ts, add column ts DATETIME; slave mysql> select * from heartbeat\G *************************** 1. row *************************** server_id: 1 file: master-bin.000002 position: 5107583 relay_master_log_file: NULL exec_master_log_pos: NULL ts: 2014-05-02 17:03:59 1 row in set (0.00 sec) CREATE TABLE `heartbeat` ( `server_id` int(10) unsigned NOT NULL, `file` varchar(255) DEFAULT NULL, `position` bigint(20) unsigned DEFAULT NULL, `relay_master_log_file` varchar(255) DEFAULT NULL, `exec_master_log_pos` bigint(20) unsigned DEFAULT NULL, `ts` datetime DEFAULT NULL, PRIMARY KEY (`server_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1
Таким образом, моя таблица сердцебиения теперь имеет 5.5 DATETIME, pt-heartbeat работает правильно, и сердцебиение воспроизводится на подчиненном устройстве. Теперь я обновлю свой мастер до MySQL 5.6:
[root@master ~]# rpm -e Percona-Server-devel-55-5.5.36-rel34.2.el6.x86_64 Percona-Server-shared-55-5.5.36-rel34.2.el6.x86_64 Percona-Server-client-55-5.5.36-rel34.2.el6.x86_64 Percona-Server-server-55-5.5.36-rel34.2.el6.x86_64 --nodeps [root@master ~]# yum install Percona-Server-server-56.x86_64 ============================================================================================================== Package Arch Version Repository Size ============================================================================================================== Installing: Percona-Server-server-56 x86_64 5.6.16-rel64.2.el6 Percona 19 M Installing for dependencies: Percona-Server-client-56 x86_64 5.6.16-rel64.2.el6 Percona 6.8 M Percona-Server-shared-56 x86_64 5.6.16-rel64.2.el6 Percona 712 k Transaction Summary ============================================================================================================== Install 3 Package(s) ... [root@master ~]# service mysql start Starting MySQL (Percona Server)....... SUCCESS! [root@master ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.6.16-64.2-56-log Percona Server (GPL), Release 64.2, Revision 569 [root@master ~]# mysql_upgrade Looking for 'mysql' as: mysql Looking for 'mysqlcheck' as: mysqlcheck Running 'mysqlcheck with default connection arguments Running 'mysqlcheck with default connection arguments mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK mysql.general_log OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK mysql.host OK mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK mysql.time_zone OK mysql.time_zone_leap_second OK mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK Running 'mysql_fix_privilege_tables'... Running 'mysqlcheck with default connection arguments Running 'mysqlcheck with default connection arguments percona.heartbeat OK OK
Теперь я могу убедиться, что запросы IKE INFORMATION_SCHEMA правильно определяют столбец «heartbeat.ts» как старый формат:
master mysql> select t.table_schema,t.engine,t.table_name,c.column_name,c.column_type from information_schema.tables t inner join information_schema.columns c on c.table_schema = t.table_schema and c.table_name = t.table_name left outer join information_schema.innodb_sys_tables ist on ist.name = concat(t.table_schema,'/',t.table_name) left outer join information_schema.innodb_sys_columns isc on isc.table_id = ist.table_id and isc.name = c.column_name where c.column_type in ('time','timestamp','datetime') and t.table_schema not in ('mysql','information_schema','performance_schema') and t.table_type = 'base table' and (t.engine != 'innodb' or (t.engine = 'innodb' and isc.mtype = 6)) order by t.table_schema,t.table_name,c.column_name; +--------------+--------+------------+-------------+-------------+ | table_schema | engine | table_name | column_name | column_type | +--------------+--------+------------+-------------+-------------+ | percona | InnoDB | heartbeat | ts | datetime | +--------------+--------+------------+-------------+-------------+ 1 row in set (0.04 sec)
Чтобы репликация работала с MySQL 5.6 до 5.5, мне также пришлось добавить несколько опций обратной совместимости на мастер:
log_bin_use_v1_row_events = ON binlog_checksum = NONE
Как только я это исправлю, я могу убедиться, что мой раб все еще работает после этого и получает пульс. Очевидно, что новые форматы не являются препятствием для обратной совместимости репликации.
slave mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.70.2 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000005 Read_Master_Log_Pos: 120 Relay_Log_File: slave-relay-bin.000002 Relay_Log_Pos: 267 Relay_Master_Log_File: master-bin.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes master mysql> select * from heartbeat; +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ | server_id | file | position | relay_master_log_file | exec_master_log_pos | ts | +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ | 1 | master-bin.000002 | 5115935 | NULL | NULL | 2014-05-02 17:04:23 | +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ 1 row in set (0.01 sec) slave mysql> select * from heartbeat; +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ | server_id | file | position | relay_master_log_file | exec_master_log_pos | ts | +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ | 1 | master-bin.000002 | 5115935 | NULL | NULL | 2014-05-02 17:04:23 | +-----------+-------------------+----------+-----------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
Но, если я не буду осторожен с MySQL 5.6 и пересоберу таблицу, новый формат явно укусит меня:
master mysql> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) master mysql> alter table percona.heartbeat force; Query OK, 1 row affected, 1 warning (0.18 sec) Records: 1 Duplicates: 0 Warnings: 1 master mysql> show warnings; +-------+------+-------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-------------------------------------------------------------------------------------+ | Note | 1880 | TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format. | +-------+------+-------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) slave mysql> show slave status\G *************************** 1. row *************************** ... Slave_IO_Running: Yes Slave_SQL_Running: No ... Last_Errno: 1677 Last_Error: Column 5 of table 'percona.heartbeat' cannot be converted from type '' to type 'datetime' ... Last_SQL_Errno: 1677 Last_SQL_Error: Column 5 of table 'percona.heartbeat' cannot be converted from type '' to type 'datetime' Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec)
TL; DR
Чему все это нас учит?
Хотя версия MySQL важна, для RBR важнее всего актуальный текущий формат каждого столбца. Ваш ведущий и ведомый (ие) ДОЛЖНЫ иметь одинаковые форматы столбцов для правильной работы RBR
Таким образом, новые временные форматы не обязательно нарушают репликацию RBR до 5.5 при условии:
- Все базовые улучшения репликации MySQL 5.6 отключены (GTID, контрольные суммы binlog и формат RBR v2)
- Таблицы с временными форматами сохраняются в своих форматах 5.5, пока все узлы 5.5 не будут удалены.
- Вы можете избежать создания каких-либо новых таблиц на мастере MySQL 5.6 с временными форматами
Однако я хочу прояснить, что репликация MySQL 5.6 — 5.5 технически не поддерживается. Я не исчерпал все возможности для проблем с репликацией RBR от 5,6 до 5,5, только этот конкретный. Если вы решите создать стратегию обновления, основанную на обратной репликации, будьте готовы к тому, что она не будет работать, и тщательно протестируйте ее заранее. Цель этого поста — просто указать, что форматы типов данных сами по себе не обязательно нарушают обратную совместимость RBR.