Ubuntu19.10でmysql5.7に接続できない

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で作るなどしても良かったかもしれないなと思いました。

最近アウトプット的なことが全然できてないと思い、久しぶりに書いてみました。
今後ちょっとしたことでも書いていく癖をつけようと思います。