MySQL 5.7のmysql_upgradeは古いDATETIME, TIME, TIMESTAMPを新しいDATETIME2, TIME2, TIMESTAMP2に変換してくれるからmysqldumpしてからリストアしなくてもいいんだぜ! っていうのが趣旨らしい。それは素敵だ。
↓これの12番目
日々の覚書: あなたのMySQL 5.6トレンド力をチェックする15の質問
ざっと見、確かにやってくれてる。worldデータベースを ダウンロード してきて食わせてみた。
(そういえば、昔はworldはMyISAMで、InnoDB版のworldが別にあったんだけど、今はたぶんInnoDBのだけなんだろうね。1つしかない)
$ cd /usr/mysql/5.5.46/ $ ./scripts/mysql_install_db --datadir=/home/yoku0825/test_55/ $ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 & $ bin/mysql -uroot < ~/world_innodb.sql $ bin/mysqladmin -uroot shutdown $ cd /usr/mysql/5.7.9 $ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 & $ bin/mysql_upgrade Checking if update is needed. Checking server version. Running queries to upgrade MySQL server. Checking system database. mysql.columns_priv OK mysql.db OK mysql.engine_cost OK mysql.event OK mysql.func OK mysql.general_log OK mysql.gtid_executed OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK mysql.host OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv error : Table upgrade required. Please do "REPAIR TABLE `proxies_priv`" or dump/reload to fix it! mysql.server_cost OK mysql.servers OK mysql.slave_master_info OK mysql.slave_relay_log_info OK mysql.slave_worker_info 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 Repairing tables mysql.proxies_priv Note : TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format. status : OK Upgrading the sys schema. Checking databases. sys.sys_config OK world.City OK world.Country OK world.CountryLanguage OK Repairing tables mysql.proxies_priv OK Upgrade process completed successfully. Checking if update is needed.
mysqlcheck --check-upgrade の後に、引っかかったやつに対してREPAIR TABLEしてくれている様子。
ちなみにデータディレクトリを作り直して5.6だと、
$ cd /usr/mysql/5.6.27 $ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 & $ bin/mysql_upgrade Looking for 'mysql' as: bin/mysql Looking for 'mysqlcheck' as: bin/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 world.City OK world.Country OK world.CountryLanguage OK OK
mysql_upgrade(というか 中身でやっぱりmysqlcheck --check-upgradeを呼んでる のでどちらかというとmysqlcheck)がそもそも警告すらしてくれない。
でも直すと直る。
mysql> ALTER TABLE mysql.proxies_priv FORCE; Query OK, 2 rows affected, 1 warning (0.00 sec) Records: 2 Duplicates: 0 Warnings: 1 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)
直るということは、その前までは旧TIMESTAMP型だったんだろうということは想像がつく。
で、取り敢えずはMySQL 5.6でできなかったことをできるようになってて5.7すごい! って言えばいいんだけど、実際に問題になるのはここではなくて、
日々の覚書: MySQL 5.6への移行でmysqldumpを使わなかったらどうなるか
( ´-`).oO(前半部分が盛大に間違っているという残念なエントリーだけどこれの2番目。
===ほぼ引用===
((マスターはmysql_upgradeでアップグレード && スレーブはmysqldumpからリストア) || (マスターはmysqldumpでアップグレード && スレーブはmysql_upgradeでアップグレード)) && (バイナリーログがROWモードで記録された) 場合に、マスターで記録された型情報とスレーブで再生されようとする型情報に不整合が発生するので、
mysql56> SHOW SLAVE STATUS\G .. Last_SQL_Errno: 1677 Last_SQL_Error: Column 0 of table 'd1.t2' cannot be converted from type 'datetime' to type 'datetime' ..
こんな訳のわからない(datetime型からdatetime型への変換に失敗した)エラーでSQLスレッドが転ける。STATEMENTモードでは影響を受けないが、binlog_format= MIXEDでROWモードにフォールバックするようなクエリーが流れているとこれの直撃を食らう。
===ここまで===
なので、マスターが旧DATETIMEでスレーブが旧DATETIMEで、絶対にmysqldumpとかしないと言い切れるなら(非推奨なことを除けば、だけど、10年も前に非推奨になったold_passwordsがこの前まで生きてたんだから、そういう世界線なんだここは)RBRのエラーも起こらないはずなので構わないといえば構わない。
どちらかというと「マスターが5.5でスレーブが5.6以降」だと、CREATE TABLEで新しくテーブルを作った時にもマスターでは旧DATETIME型、スレーブでは新DATETIME型になってこれを踏むことになる。これはmysql_upgradeを使ったインプレースアップグレードだったか、mysqldumpを使ったダンプアップグレードだったかは 関係ない ので、5.5と5.6の間をまたぐレプリケーションはそう長く運用しない方がいい。
スレーブ作り直すの大変だ