Edited at

Homebrew で MySQL を 5.7.22 から 8.0.11 にバージョンアップしたら Rails が動かなくなったので対処する

More than 1 year has passed since last update.


要約


  • MySQL 5.7.22 を入れていた PC に Homebrew で 8.0.11 をインストールしてしまい、Rails が動かなくなった


  • mysql2mysqlclientライブラリへの再リンクは bundle exec gem uninstall mysql2 && bundle installで解決


  • mysql_upgrade -urootで MySQL サーバをアップグレードし、データベース側の問題も解決することで Rails が再び動き出した


発生事象

いつものようにbrew update && brew upgradeした後、rails gでとある Gem の初期ファイルを生成しようとしたところ、以下のエラーが発生。


console

/Users/hoge/rails/example/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require': dlopen(/Users/hoge/rails/example/vendor/bundle/ruby/2.5.0/gems/mysql2-0.5.1/lib/mysql2/mysql2.bundle, 9): Library not loaded: /usr/local/opt/mysql/lib/libmysqlclient.20.dylib (LoadError)

Referenced from: /Users/hoge/rails/example/vendor/bundle/ruby/2.5.0/gems/mysql2-0.5.1/lib/mysql2/mysql2.bundle
Reason: image not found - /Users/hoge/rails/example/vendor/bundle/ruby/2.5.0/gems/mysql2-0.5.1/lib/mysql2/mysql2.bundle

/usr/local/opt/mysql/lib/libmysqlclient.20.dylibファイルが見つからないため、エラーが発生しているようだ。

念のため、/usr/local/opt/mysql/libを確認してみる。


console

$ ls -l /usr/local/opt/mysql/lib

total 22424
-r--r--r-- 1 hoge admin 5423044 6 15 12:22 libmysqlclient.21.dylib
-r--r--r-- 1 hoge admin 6041280 4 8 16:02 libmysqlclient.a
lrwxr-xr-x 1 hoge admin 23 4 8 16:02 libmysqlclient.dylib -> libmysqlclient.21.dylib
-r--r--r-- 1 hoge admin 9624 4 8 16:02 libmysqlservices.a
drwxr-xr-x 3 hoge admin 102 6 15 12:22 pkgconfig
drwxr-xr-x 91 hoge admin 3094 4 8 16:02 plugin

確かにlibmysqlclient.20.dylibがなく、代わりにlibmysqlclient.21.dylibが存在している。

brew upgrademysqlclientがアップデートされてしまったためだろうか。


対処その1:Gem に最新のmysqlclientライブラリをリンクさせる

調べたところ、libmysqlclient.20.dylibへのシンボリックリンクを/usr/local/opt/mysql/libに設置すれば良さそうだ。

libmysqlclient.20.dylibを探してみる。


console

$ find /usr -name 'libmysqlclient.20.dylib'

/usr/local/Cellar/mysql/5.7.22/lib/libmysqlclient.20.dylib
find: /usr/sbin/authserver: Permission denied

Homebrew でインストールした MySQL ライブラリが残っていた。

その後もう少し調べたところ、僕の PC には MySQL 5.7.22 と MySQL 8.0.11 がインストールされており、5.7.22 はlibmysqlclient.20.dylib、8.0.11 はlibmysqlclient.21.dylibを使用しているらしいということが分かった。

シンボリックリンクを設置する方法はあまり美しくないし、今後は MySQL 8.0 以降が使われていくだろうから、できれば最新のライブラリを使うようにしたい。

そうなると Gem を更新し、mysqlclientライブラリを再リンクする必要がありそう。

bundle doctorによると、今回問題になっている Gem はmysql2のみのようだ。


console

$ bundle doctor

The Gemfile's dependencies are satisfied
The following gems are missing OS dependencies:
* mysql2: /usr/local/opt/mysql/lib/libmysqlclient.20.dylib

mysql2を個別にアンインストール→再インストールしてみる。


console

$ bundle exec gem uninstall mysql2

Successfully uninstalled mysql2-0.5.1
$ bundle install
(略)
Fetching mysql2 0.5.1
Installing mysql2 0.5.1 with native extensions
(略)
Bundle complete! 29 Gemfile dependencies, 118 gems now installed.
Bundled gems are installed into `./vendor/bundle`
$ bundle doctor
The Gemfile's dependencies are satisfied
No issues found with the installed bundle

リンクの問題は解消されたので、もう一度rails gを実行してみると、今度は別のエラーが。


console

/Users/hoge/rails/example/vendor/bundle/ruby/2.5.0/gems/mysql2-0.5.1/lib/mysql2/client.rb:131:in `_query': Mysql2::Error::ConnectionError: Access denied for user 'example'@'localhost' (using password: YES): SELECT table_name FROM information_schema.tables WHERE table_schema = database() (ActiveRecord::StatementInvalid)


調べてみると今度は MySQL のアップグレードが必要らしい。


対処その2:MySQL サーバのアップグレード

まずはアップグレードに失敗した時のためのバックアップを取ろうとしたが、エラーが発生。


console

$ mysqldump -uroot --databases example_development example_test --column-statistics=0 --single-transaction > ./tmp/db_backup.dump

Password:
mysqldump: Error: 'The user specified as a definer ('mysql.infoschema'@'localhost') does not exist' when trying to dump tablespaces

MySQL 5.7 クライアントからデータベース操作しようとしても上記のようなエラーが出る。

(つまり対処その1でlibmysqlclient.20.dylibを継続利用しようとしても同様のエラーが発生したはず)

仕方ないので、成功するかどうか分からないがアップグレードをかける。


console

$ mysql_upgrade -uroot

Checking if update is needed.
Checking server version.
Running queries to upgrade MySQL server.
Upgrading system table data.
Checking system database.
mysql.columns_priv OK
mysql.component OK
mysql.db OK
mysql.default_roles OK
mysql.engine_cost OK
mysql.func OK
mysql.general_log OK
mysql.global_grants OK
mysql.gtid_executed OK
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
mysql.help_topic OK
mysql.innodb_index_stats OK
mysql.innodb_table_stats OK
mysql.ndb_binlog_index OK
mysql.password_history OK
mysql.plugin OK
mysql.procs_priv OK
mysql.proxies_priv OK
mysql.role_edges OK
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
Found outdated sys schema version 1.5.1.
Upgrading the sys schema.
Checking databases.
example_development.ar_internal_metadata OK
example_development.hogehoge OK
example_development.schema_migrations OK
example_test.ar_internal_metadata OK
example_test.hogehoge OK
example_test.schema_migrations OK
sys.sys_config OK
Upgrade process completed successfully.
Checking if update is needed.

なんとか成功した。

その後rails gを実行したところ、エラーは発生せず、目的の初期ファイルが生成された。

また、データベース操作系のタスクも実行し、エラーが発生しないことを確認した。


備考

MySQL 8.0.11 は本当に今回のbrew update && brew upgradeの時に自動でインストールされてしまったものなのだろうか?

メジャーアップデートで大幅な変更が施されているそうなので、brew upgradeで勝手にメジャーバージョンアップするのだとしたらかなり問題になりそうなのだが…。

それとも以前に自分が最新バージョンを試してみたくなって 8.0 系を手動でインストールしたのだろうか?

それで MySQL サーバの再起動によって今回 5.7 → 8.0 に意図せず切り替わってしまったとか…。

記憶は定かではない。