Oracle RPM の MySQL はアップデート時にサービスが enable にされる

Oracle の YUM リポジトリの RPM でインストールした MySQL だと、インストール時だけでなくアップデート時にもサービスが enable されるため、何かしらの事情でインストール後に disable していてもアップデートで enable になってしまいます。

Oracle の RPM の MySQL

適当な非最新のバージョンをインストールします。

dnf install -y https://dev.mysql.com/get/mysql80-community-release-el9-4.noarch.rpm
dnf install -y mysql-community-server-8.0.33

インストール直後は enabled になっています。

systemctl is-enabled mysqld.service
# enabled

systemctl で disable にします。

systemctl disable mysqld.service
# Removed "/etc/systemd/system/multi-user.target.wants/mysqld.service".

systemctl is-enabled mysqld.service
# disabled

アップデートすると enabled に戻ります。

dnf update -y mysql-community-server
# ...

systemctl is-enabled mysqld.service
# enabled

原因

RPM の spec ファイルの詳しいことはわかりませんがこの辺りが怪しいと思います。

https://github.com/mysql/mysql-server/blob/057f5c9509c6c9ea3ce3acdc619f3353c09e6ec6/packaging/rpm-fedora/mysql.spec.in#L659

%post セクションに以下が含まれているためインストールやアップデートのたびに enable されるのではないかと。

/usr/bin/systemctl enable mysqld >/dev/null 2>&1 || :

%systemd_post mysqld.service/usr/lib/rpm/macros.d/macros.systemd などの内容から察するに新規インストール時に systemctl --no-reload preset mysqld.service するためのマクロのようです。

rpm -q --scripts mysql-community-server でみると postinstall は次のようになっていました。

[ -e /var/log/mysqld.log ] || install -m0640 -omysql -gmysql /dev/null /var/log/mysqld.log >/dev/null 2>&1 || :

if [ $1 -eq 1 ] && [ -x "/usr/lib/systemd/systemd-update-helper" ]; then
    # Initial installation
    /usr/lib/systemd/systemd-update-helper install-system-units mysqld.service || :
fi

/usr/bin/systemctl enable mysqld >/dev/null 2>&1 || :

以下の通り $1 は新規インストール時には 1 に、アップデート時は 2 になるので、その値でもって新規インストール時にのみ enable にする方が良い気がしないでもないです。

Scriptlets :: Fedora Docs

ワークアラウンド

mask しておけばサービスが enable になるのを阻止できます。

systemctl mask mysqld.service
# Created symlink /etc/systemd/system/mysqld.service → /dev/null.

systemctl is-enabled mysqld.service
# masked

dnf update -y mysql-community-server
# ...

systemctl is-enabled mysqld.service
# masked

RHEL の mysql-server

RHEL9 の mysql-server だとそうはなっていませんでした。

cat /etc/redhat-release
# Red Hat Enterprise Linux release 9.2 (Plow)

dnf install mysql-server
# ...

systemctl is-enabled mysqld.service
# disabled

rpm -q --scripts mysql-server の postinstall の抜粋です。

if [ $1 -eq 1 ] && [ -x "/usr/lib/systemd/systemd-update-helper" ]; then
    # Initial installation
    /usr/lib/systemd/systemd-update-helper install-system-units mysqld.service || :
fi

if [ ! -e "/var/log/mysql/mysqld.log" -a ! -h "/var/log/mysql/mysqld.log" ] ; then
    install /dev/null -m0640 -omysql -gmysql "/var/log/mysql/mysqld.log"
fi

systemd.preset

という話を社内でしたところ「preset: disabled ってなんだ?」という話になりました。

これはシステムへのインストール時にデフォルトで disabled とするか enabled とするかの意味です。例えば sshd などであれば preset: enabled なのでシステムへのインストール時にデフォルトで enabled となり、不要なら明示的に disable する必要があります。

preset は以下のファイルで設定可能です。

/etc/systemd/system-preset/*.preset
/run/systemd/system-preset/*.preset
/usr/lib/systemd/system-preset/*.preset
/etc/systemd/user-preset/*.preset
/run/systemd/user-preset/*.preset
/usr/lib/systemd/user-preset/*.preset

RHEL9 で見てみると /usr/lib/systemd/system-preset/*.preset/usr/lib/systemd/user-preset/*.preset でシステム用に設定されています。この設定に基づいて rpm の %systemd_post マクロから呼ばれる systemctl preset サービス名 コマンドで enable/disable される、という仕組みのようです。

なお preset はデフォルトで enable のため /usr/lib/systemd/system-preset/99-default-disable.preset ですべて無効に設定されています。

cat /usr/lib/systemd/system-preset/99-default-disable.preset
# disable *

例えば epel-release をインストールすると /usr/lib/systemd/system-preset/90-epel.preset に次のファイルが作成されます。

# Also see:
# https://fedoraproject.org/wiki/Starting_services_by_default
#
# https://bugzilla.redhat.com/show_bug.cgi?id=1901721
enable x509watch.timer
#
# https://bugzilla.redhat.com/show_bug.cgi?id=1986205
#
enable certbot-renew.timer

新規インストール時に有効にするだけであれば同じような方法でやるのが筋のようにも思います。つまり mysql80-community-release のインストール時に /usr/lib/systemd/system-preset/90-mysql-community.preset みたいなファイルで enabled mysqld.service を指定する、とかです。

Not a bug

MySQL Bugs: #112382: Update mysql server with yum/dnf ensures service is always enabled

そうなるだろうとは思っていたけれども。

さいごに

基本的にはサービスを開始しないならインストールしなければ良いということだと思いますが、例えばサービスが Pacemaker で管理されているので systemd からは起動してほしくないような場合は注意が必要そうです。

10年ぐらい前からこうだったと思います。CentOS 7 で MySQL をインストールするために Oracle の YUM リポジトリの RPM を使う必要がありました。RHEL8 系以降では AppStream などからも MySQL がインストールできるので最新が必要とかでなければそちらのリポジトリからインストールする方が良いかもしれません。