MySQLのレプリケーションのエラー

MySQLをアップデートしたらレプリケーションにエラーが出て動かなくなった。

現象

MySQL 5.7.13から5.7.14にアップデートしたところ、次のようなエラーが出てレプリケーションが動かなくなった。

2016-09-17T05:06:04.346580Z 0 [ERROR] Info table has a problem with its key field(s). Table 'mysql.slave_master_info' expected field #23 to be 'Channel_name' but found 'Tls_version' instead.
2016-09-17T05:06:04.346679Z 0 [ERROR] Error in checking mysql.slave_master_info repository info type of TABLE.
2016-09-17T05:06:04.346798Z 0 [ERROR] Error creating master info: Error checking repositories.
2016-09-17T05:06:04.346869Z 0 [ERROR] Failed to create or recover replication info repository.
2016-09-17T05:06:04.346902Z 0 [ERROR] Failed to create or recover replication info repositories.

リスタートしても一緒。mysql_upgradeを実行しても変わらず。

原因

MySQL 5.7.14のmysql_upgradeの不具合により、mysql.slave_master_infoテーブルが適切に更新されないため。

対策

mysqlを管理者権限で起動し、次のようにテーブルをリファインする。

USE mysql;

ALTER TABLE `mysql`.`slave_master_info`
CHANGE COLUMN `Channel_name` `Channel_name` CHAR(64) NOT NULL DEFAULT '' COMMENT 'The channel on which the slave is connected to a source. Used in Multisource Replication' AFTER `Enabled_auto_position`;

CREATE TABLE `new_slave_master_info` (
 `Number_of_lines` int(10) unsigned NOT NULL COMMENT 'Number of lines in the file.',
 `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'The name of the master binary log currently being read from the master.',
 `Master_log_pos` bigint(20) unsigned NOT NULL COMMENT 'The master log position of the last read event.',
 `Host` char(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT 'The host name of the master.',
 `User_name` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The user name used to connect to the master.',
 `User_password` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The password used to connect to the master.',
 `Port` int(10) unsigned NOT NULL COMMENT 'The network port used to connect to the master.',
 `Connect_retry` int(10) unsigned NOT NULL COMMENT 'The period (in seconds) that the slave will wait before trying to reconnect to the master.',
 `Enabled_ssl` tinyint(1) NOT NULL COMMENT 'Indicates whether the server supports SSL connections.',
 `Ssl_ca` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The file used for the Certificate Authority (CA) certificate.',
 `Ssl_capath` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The path to the Certificate Authority (CA) certificates.',
 `Ssl_cert` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The name of the SSL certificate file.',
 `Ssl_cipher` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The name of the cipher in use for the SSL connection.',
 `Ssl_key` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The name of the SSL key file.',
 `Ssl_verify_server_cert` tinyint(1) NOT NULL COMMENT 'Whether to verify the server certificate.',
 `Heartbeat` float NOT NULL,
 `Bind` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'Displays which interface is employed when connecting to the MySQL server',
 `Ignored_server_ids` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The number of server IDs to be ignored, followed by the actual server IDs',
 `Uuid` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The master server uuid.',
 `Retry_count` bigint(20) unsigned NOT NULL COMMENT 'Number of reconnect attempts, to the master, before giving up.',
 `Ssl_crl` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The file used for the Certificate Revocation List (CRL)',
 `Ssl_crlpath` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'The path used for Certificate Revocation List (CRL) files',
 `Enabled_auto_position` tinyint(1) NOT NULL COMMENT 'Indicates whether GTIDs will be used to retrieve events from the master.',
 `Channel_name` char(64) NOT NULL COMMENT 'The channel on which the slave is connected to a source. Used in Multisource Replication',
 `Tls_version` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT 'Tls version',
 PRIMARY KEY (`Channel_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Master Information';

INSERT INTO `new_slave_master_info` SELECT * FROM slave_master_info;

DROP TABLE `slave_master_info`;

RENAME TABLE `new_slave_master_info` to `slave_master_info`;

cf. mysql_upgrade of PS 5.7.14 doesn’t update the “slave_master_info” schema (Percona Server bug report)

おまけのトラブル

上記の解決策を試す前に、不具合報告ページの最後にある「mysql.slave_master_infoテーブルを削除してmysql_upgradeを実行すれば良い」という安易な解法を試してしまい、その結果、マスター側で次のようなエラーが出るように。

2016-11-29T11:47:50.604968Z 1 [ERROR] Error reading packet from server for channel '': The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires. (server_errno=1236)
2016-11-29T11:47:50.605017Z 1 [ERROR] Slave I/O for channel '': Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.', Error_code: 1236

まあ、そうだよね…。

仕方がないので、レプリケーションを再構築。

  1. マスター側でdumpファイルを作成。
    # mysql -u root -p
    Enter Password:
    mysql> show master status\G
    *************************** 1. row ***************************
     File: mysql-bin.000023
     Position: 1288527
     Binlog_Do_DB:
     Binlog_Ignore_DB:
    Executed_Gtid_Set: 3e7e83f4-14fb-11e6-9cd7-525406009008:1-1947619
    1 row in set (0.00 sec)
    mysql> quit;
    # mysqldump --all-databases --single-transaction --flush-logs --triggers --routines --events --add-drop-table -p > ~/master.sql
  2. スレーブ側でレプリケーションをいったん停止し、マスターをリセット。
    # mysql -u root -p
    Enter Password:
    mysql> stop slave;
    mysql> reset slave;
    mysql> reset master;
    mysql> quit;
    #
  3. スレーブ側にデータベースをリストア。
    # mysql -p < master.sql
  4. レプリケーション再同期。
    # mysql -u root -p
    Enter Password:
    mysql> change master to
        -> master_host=’********’,
        -> master_user=’*********’,
        -> master_password=’*********’,
        -> master_log_file=’mysql-bin.000003”,
        -> master_log_pos=2376;

    MASTER_LOG_FILE および MASTER_LOG_POS は、マスター側の「show master status」で確認した情報をもとに入力。

  5. スレーブ側のレプリケーションを再開。
    mysql> start slave
  6. スレーブ側でレプリケーションが正常に動いているか確認。
    mysql> show slave status\G

    ここで、次のパラメータがふたつとも「Yes」なら問題なし。

    • Slave_IO_Running
    • Slave_SQL_Running
タイトルとURLをコピーしました