Ubuntu19.10でPython経由でmysqlに接続できなくてどちゃくそハマったので備忘録としてまとめます。
前提
今まで接続できていたPythonでのmysqlへの接続がエラーになりました。
エラーメッセージはだいぶ省略していますが、以下のように出ていました。
$ python manage.py showmigrations
ImportError: libmysqlclient.so.20: cannot open shared object file: No such file or directory
エラーになったときの環境
- Ubuntu 19.10
- mysql 5.7(接続しようとしているlocal環境のdockerのmysql)
- libmysqlclient21 8.0.17-0ubuntu2
- libmysqlclient-dev 8.0.17-0ubuntu2
- Python 3.7.3
- django 2.2.4
- mysqlclient 1.4.2.post1
エラー原因
ちょうど昨日Ubuntu19.04から19.10にアップデートしました。
原因を詳しく調べたわけではないですが、アップデートによりlibmysqlclientがmysql8に対応したことにより起きたエラーだと考えています。(あまり使ったことないので知らなかったのですが、mysql5.7 -> 8にアップデートしたらしい)
このあたりを見た感じはmysql8に対応したのは19.10のeoanからっぽいです。
https://www.ubuntuupdates.org/package_metas?q=libmysqlclient-dev
余談ですが、Ubuntu19.10より19.04の方がデザインが好きでした、狼かっこよかった。
対策(失敗)
エラーメッセージを見る限り、要はlibmysqlclient.so.20ファイルがないようです。
以下のようにlibmysqlclient.so.21はありました。
/usr/lib/x86_64-linux-gnu/libmysqlclient.so.21
なので、20 -> 21へのシンボリックリンクを作成すればいけるのではと思いました。
作成します。
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libmysqlclient.so.21 /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20
これで再度pythonコマンドを実行します、すると以下のエラーが...
ImportError: /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20: version `libmysqlclient_20.0' not found
Pythonのほうでversionチェックを行ってるのですかね?おそらく。
シンボリックリンクを作成するのではダメだとわかりました。
削除しておきます。
sudo unlink /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20
対策(成功)
libmysqlclient.so.20が動作することが必要なので、libmysqlclientとlibmysqlclient-devをダウングレードして再度インストールします。
aptでダウングレードしてインストールするのは初めてでした。
パッケージの情報は以下のようにして表示できます。
$ apt-cache showpkg libmysqlclient20 libmysqlclient-dev
そして以下のサイトからlibmysqlclient20_5.7.28とlibmysqlclient-dev_5.7.28のdebファイルをインストールします。
最初間違ってlibmysqlclient-dev_5.7.27-0ubuntu0.19.04.1_amd64.debをインストールしてしまってlibmysqlclient20とバージョン合わなくてうまくいかないということもありました。なので若干コマンドの順番前後してたりとかはあるかもしれません...
https://ubuntu.pkgs.org/19.04/mysql-5.7-amd64/libmysqlclient20_5.7.28-1ubuntu19.04_amd64.deb.html
https://ubuntu.pkgs.org/19.04/mysql-5.7-amd64/libmysqlclient-dev_5.7.28-1ubuntu19.04_amd64.deb.html
ダウンロードしたdebファイルをdpkgで入れます。
$ sudo dpkg -i libmysqlclient-dev_5.7.28-1ubuntu19.04_amd64.deb
$ sudo dpkg -i libmysqlclient20_5.7.28-1ubuntu19.04_amd64.deb
そしてupdateして、version指定してインストールします。
ちょっとこのあたり記憶が曖昧です、間違ってたらすみません...
$ sudo apt update
$ sudo apt install libmysqlclient-dev=5.7.28-1ubuntu19.04
$ sudo apt install libmysqlclient20_5.7.28-1ubuntu19.04
これで私の環境では以下のようになりました。
i libmysqlclient-dev 5.7.28-1ubuntu19.04 amd64 MySQL development headers
ii libmysqlclient20:amd64 5.7.28-1ubuntu19.04 amd64 MySQL shared client libraries
ii libmysqlclient21:amd64 8.0.17-0ubuntu2 amd64 MySQL database client library
Pythonを再度実行したらうまく接続できたようです!
しかしこのままではバージョンが低いものをインストールしているせいで、更新通知がくるのでバージョンを一旦固定にします。
$ sudo apt-mark hold libmysqlclient20
$ sudo apt-mark hold libmysqlclient-dev
これで通知は来なくなりました。解除するときはunholdを使うようです。
apt-mark unhold パッケージ名
所感
バージョン変えたことにより、接続できなかったり問題は発生したんですが調べてると結構色々勉強になりました。
途中やってて気づいたのですが、ローカル開発環境ですしmysqlのバージョンを8にしたりPythonの環境をdockerで作るなどしても良かったかもしれないなと思いました。
最近アウトプット的なことが全然できてないと思い、久しぶりに書いてみました。
今後ちょっとしたことでも書いていく癖をつけようと思います。