MariaDB 11.8.3へアップグレード後、rootユーザにunix_socketで接続できなくなる
こんばんは。tukapiyoです。
Debian 12(Bookworm)からDebian 13(Trixie)にアップグレードしたところ、MariaDB 10.11系から11.8.3へアップグレードされました。
正常に動作しているように見えたのですが、rootユーザでログインできなくなっていることに気づきました。
今回はこの事象を調査し、解消した記録です。
目次
発生事象
mysqldumpの失敗
最初に気づいたのは、cronでmysqldumpに失敗したエラーメールが届いたタイミングでした。
以下の様なメールが届きました。
mysqldump: Got error: 1698: "Access denied for user 'root'@'localhost'" when trying to connect
これはおかしいということで調査を始めました。
mysqlで接続できない
rootユーザからmysqlコマンドで接続しようとしても接続できません。
なお慣れているのでmysqlコマンドを実行していますが、mariadbコマンドを実行するのが今のやり方です。
$ sudo su - # mysql -uroot ERROR 1698 (28000): Access denied for user 'root'@'localhost'
なお、rootではないパスワード認証をしているユーザは問題なく接続できます。
そのせいもあってしばらく気づかなかったというのがあります。
調査
rootで認証
色々な方法でログインを試してみます。
# mysql -uroot --socket=/run/mysqld/mysqld.sock ERROR 1698 (28000): Access denied for user 'root'@'localhost' # mysql -uroot -p --socket=/run/mysqld/mysqld.sock Enter password: ERROR 1698 (28000): Access denied for user 'root'@'localhost' # mysql -uroot --socket=/var/run/mysqld/mysqld.sock ERROR 1698 (28000): Access denied for user 'root'@'localhost' # mysql -uroot --protocol=TCP WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login. ERROR 1698 (28000): Access denied for user 'root'@'localhost' # mysql -uroot -p --protocol=TCP Enter password: ERROR 1698 (28000): Access denied for user 'root'@'localhost'
どれもだめですね。
journalctlでログ確認
mariadb.serviceのログを確認してみると以下の様に警告が出ていることが分かりました。
MariaDBをアップグレードしたからか(?)、mariadb-upgradeを実行しようとして失敗しているようです。
# journalctl -xeu mariadb (..snip..) /etc/mysql/debian-start[14886]: /usr/bin/mariadb-upgrade: the '--basedir' option is always ignored /etc/mysql/debian-start[14886]: Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client /etc/mysql/debian-start[14886]: ERROR 1698 (28000): Access denied for user 'root'@'localhost' /etc/mysql/debian-start[14886]: FATAL ERROR: Upgrade failed (..snip..)
mysqld-safeで強制ログインして確認
仕方ないので強制的にログインすることにします。
動作しているmariadb-serverを停止させてから、mysqld-safeコマンドに--skip-grant-tablesをつけて起動すれば認証をスキップできるようになります。
なお、mysqld-safeも同様に今風のコマンドはmariadbd-safeです。
# systemctl stop mariadb # mysqld-safe --skip-grant-tables & # mysqld -uroot MariaDB [(none)]>
global_privの確認
ユーザの権限を確認します。
最近のMariaDBでは、mysqlデータベースのglobal_privテーブルに情報が保存されるようです。
MariaDB [(none)]> SELECT * FROM mysql.global_priv;
出力が長いので結果は省略しますが、権限がJSON形式で表示されます。
root@localhostの権限を抜粋すると、以下の様になっていました。
"plugin":"unix_socket","authentication_string":"*XXXXXXXXXXXXXXXXXXXXXXXXX"
authentication_stringはパスワードハッシュなので隠していますが値が入っています。
pluginsの確認
rootユーザはsocketでログインする設定になっていましたので、unix_socketプラグインが読み込まれているかどうか確認します。
MariaDB [(none)]> SHOW plugins; +---------------------+----------+--------------------+--------------------+---------+ | Name | Status | Type | Library | License | +---------------------+----------+--------------------+--------------------+---------+ (..snip..) | unix_socket | ACTIVE | AUTHENTICATION | NULL | GPL | (..snip..)
unix_socketが表示されているので、どうやら読み込まれているようです。
試行錯誤
パスワード認証へ変更
一度パスワード認証へ変更してみます。
global_privテーブルの中をJSONを書き換えます。
MariaDB [(none)]> UPDATE mysql.global_priv SET priv = JSON_SET(priv, '$.plugin', 'mysql_native_password') WHERE User = 'root' AND Host = 'localhost'; Query OK, 1 row affected (0.001 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [(none)]> \q Bye
書き換えたら、バックグラウンドで動作させているmysqld_safeを終了しMariaDBを通常起動させます。
# jobs [1]+ Running mysqld_safe --skip-grant-tables & # kill %1 # jobs [1]+ Done mysqld_safe --skip-grant-tables # systemctl start mariadb
この状態でログインを試してみます。
# mysql -uroot ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) # mysql -uroot -p Enter password: MariaDB [(none)]> \q Bye
パスワード認証で入ることができましたね。
でもこれでは解決していません。
ちなみにjournalctlでログを見てみますとメッセージが変わっています。
# journalctl -xeu mariadb (..snip..) /etc/mysql/debian-start[20979]: /usr/bin/mariadb-upgrade: the '--basedir' option is always ignored /etc/mysql/debian-start[20979]: Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client /etc/mysql/debian-start[20979]: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) /etc/mysql/debian-start[20979]: FATAL ERROR: Upgrade failed (..snip..)
以前はERROR 1698でしたが、ERROR 1045でパスワードが未指定なのでアクセスできないというメッセージに変わりました。
パスワード認証になったので当然ですね。
mariadb-upgrade
無事にrootでログインできるようになったことですし、データベースのアップグレードをしたら変わるかもしれません。
手動でmariadb-upgradeを実行してみましょう。
# mariadb-upgrade -p Enter password: Phase 1/8: Checking and upgrading mysql database Processing databases mysql mysql.column_stats OK (..snip..) Phase 7/8: uninstalling plugins Phase 8/8: Running 'FLUSH PRIVILEGES' OK
データベースのアップグレードは無事に完了しました。
ソケット認証に変更(UPDATE)
それではソケット認証にもう一度戻して状況を確認してみましょう。
変更後mariadb.serviceを再起動します。
# mysql -uroot -p Enter password: MariaDB [(none)]> UPDATE mysql.global_priv SET priv = JSON_SET(priv, '$.plugin', 'unix_socket') WHERE User = 'root' AND Host = 'localhost'; Query OK, 1 row affected (0.001 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [(none)]> \q Bye # systemctl stop mariadb # systemctl start mariadb
状況を確認してみましょう。
# mysql -uroot ERROR 1698 (28000): Access denied for user 'root'@'localhost' # mysql -uroot -p Enter password: ERROR 1698 (28000): Access denied for user 'root'@'localhost' # journalctl -xeu mariadb (..snip..) /etc/mysql/debian-start[21117]: /usr/bin/mariadb-upgrade: the '--basedir' option is always ignored /etc/mysql/debian-start[21117]: Reading datadir from the MariaDB server failed. Got the following error when executing the 'mysql' command line client /etc/mysql/debian-start[21117]: ERROR 1698 (28000): Access denied for user 'root'@'localhost' /etc/mysql/debian-start[21117]: FATAL ERROR: Upgrade failed (..snip..)
見ての通り何も解決していません。
mariadb-upgradeを手動で実行しても解決しませんでしたし、そもそもmariadb-upgradeはサービス起動時に毎回実行しているようです。
解決
ソケット認証に変更2回目(ALTER)
MariaDBの認証周りの仕様を確認しようと思い、公式ドキュメントを漁ってみました。
すると、認証方式の変更方法が間違っていることに気づきます。
UPDATEではなく、ALTER使えとのこと。
試してみましょう。
現在はまたrootにログインできない状況ですので、まずはmysqld_safeで再起動をしてパスワード認証へ変更後、改めてサービスを起動します。
ここではまだUPDATEで変更します(パスワード認証への変更はUPDATEでも問題なかったため)。
# mysqld_safe --skip-grant-tables & # mysql -uroot MariaDB [(none)]> UPDATE mysql.global_priv SET priv = JSON_SET(priv, '$.plugin', 'mysql_native_password') WHERE User = 'root' AND Host = 'localhost'; Query OK, 1 row affected (0.001 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [(none)]> \q Bye # jobs [1]+ Running mysqld_safe --skip-grant-tables & # kill %1 # jobs [1]+ Done mysqld_safe --skip-grant-tables # systemctl start mariadb
ALTERで認証方式を変更します。
ALTER前後のglobal_privも見たくなったので見ておきます。
# mysql -uroot -p Enter password: MariaDB [(none)]> SELECT * FROM mysql.global_priv; (..snip..) "plugin":"mysql_native_password","authentication_string":"*XXXXXXXXXXXXXXXXXXXXXXXXX" (..snip..) MariaDB [(none)]> ALTER USER root@localhost IDENTIFIED VIA unix_socket; Query OK, 0 rows affected (0.001 sec) MariaDB [(none)]> select * from mysql.global_priv; (..snip..) "plugin":"unix_socket","authentication_string":"" (..snip..) MariaDB [(none)]> \q Bye
なんと、authentication_stringが空欄になりました。
unix_socket認証だとパスワード不要なので当然と言えば当然ですが、何となく原因がこれな気がしてきます。
認証
再度ログインを試してみましょう。
# mysql -uroot MariaDB [(none)]> \q Bye
ログインできましたね…
念のためmariadb.serviceを再起動してから試してみましょう。
# systemctl stop mariadb # systemctl start mariadb # mysql -uroot MariaDB [(none)]> \q Bye
ログインできました!
journalctlでログ確認
mariadb.service再起動後のログも見てみます。
# journalctl -xeu mariadb (..snip..) /etc/mysql/debian-start[21776]: /usr/bin/mariadb-upgrade: the '--basedir' option is always ignored (..snip..)
mariadbd-upgradeの認証失敗エラーが消えています!
原因
どうやら、unix_socketで認証する設定のとき、authentication_string(つまりはパスワード)が設定されているとログインできなくなるようです。
もう少し確認を進めてみます。
パスワードの設定
unix_socketにパスワードを設定してみます…と、パスワードを設定するのは許されないようです。
# mysql -uroot
MariaDB [(none)]> SET PASSWORD = PASSWORD('hogehogefugafuga');
ERROR 1699 (HY000): SET PASSWORD is not applicable for users authenticating via unix_socket plugin
MariaDB [(none)]> \q
Bye
ちなみに、UPDATEでauthentication_stringを設定すると普通に設定できるのですが、その後ログインできなくなるかと言えば、できてしまいました。
あえてログは載せませんが。
結論
- 何らかの不整合が発生していたと思われる
- ログインできなくなったら、
mysqld_safe --skip-grant-tables unix_socket利用時はパスワードを設定しないALTERコマンドで認証方式を設定する(と直る?)


最近のコメント