Upgrading Directly from MySQL 5.0 to 5.7 using an ‘In Place’ Upgrade | MySQL Server Blog を読んでふと思い立ったので。
MySQL 5.7のmysql_upgradeは古いDATETIME, TIME, TIMESTAMPを新しいDATETIME2, TIME2, TIMESTAMP2に変換してくれるからmysqldumpしてからリストアしなくてもいいんだぜ! っていうのが趣旨らしい。それは素敵だ。
↓これの12番目
日々の覚書: あなたのMySQL 5.6トレンド力をチェックする15の質問
ざっと見、確かにやってくれてる。worldデータベースを ダウンロードしてきて食わせてみた。
(そういえば、昔はworldはMyISAMで、InnoDB版のworldが別にあったんだけど、今はたぶんInnoDBのだけなんだろうね。1つしかない)
mysqlcheck --check-upgrade の後に、引っかかったやつに対してREPAIR TABLEしてくれている様子。
ちなみにデータディレクトリを作り直して5.6だと、
mysql_upgrade(というか 中身でやっぱりmysqlcheck --check-upgradeを呼んでるのでどちらかというとmysqlcheck)がそもそも警告すらしてくれない。
でも直すと直る。
直るということは、その前までは旧TIMESTAMP型だったんだろうということは想像がつく。
で、取り敢えずはMySQL 5.6でできなかったことをできるようになってて5.7すごい! って言えばいいんだけど、実際に問題になるのはここではなくて、
日々の覚書: MySQL 5.6への移行でmysqldumpを使わなかったらどうなるか
( ´-`).oO(前半部分が盛大に間違っているという残念なエントリーだけどこれの2番目。
===ほぼ引用===
((マスターはmysql_upgradeでアップグレード && スレーブはmysqldumpからリストア) || (マスターはmysqldumpでアップグレード && スレーブはmysql_upgradeでアップグレード)) && (バイナリーログがROWモードで記録された) 場合に、マスターで記録された型情報とスレーブで再生されようとする型情報に不整合が発生するので、
こんな訳のわからない(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の間をまたぐレプリケーションはそう長く運用しない方がいい。
スレーブ作り直すの大変だったと思うよ。
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の間をまたぐレプリケーションはそう長く運用しない方がいい。
スレーブ作り直すの大変だ