MySQLでユーザーを確認する方法|権限表示やユーザー作成も

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips > MySQLでユーザーを確認する方法|権限表示やユーザー作成も
「MySQLのユーザーが増えてきて、誰がどのデータベースにアクセスできるのか把握できなくなってきた」
MySQLを運用していると、ユーザー管理が複雑になりがちです。

この記事では、MySQLのユーザー一覧を確認する SELECT user と、権限を確認する SHOW GRANTS の実践的な使い方を解説します。
ユーザーの作成・権限付与・削除まで、現場で使う操作をひととおりカバーします。

この記事のポイント

・MySQLのユーザー一覧は SELECT User, Host FROM mysql.user; で確認できる
・ユーザーの権限確認は SHOW GRANTS FOR 'ユーザー'@'ホスト'; を使う
・Host列の % は全ホスト許可を意味し、セキュリティ上の注意が必要
・MariaDB(RHEL/CentOS 7以降のデフォルト)でもSQL文は基本同じ


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

MySQLにログインする

ユーザー管理の操作は、MySQLにログインしてから行います。

# MySQLにrootユーザーでログイン $ mysql -u root -p Enter password: mysql>

MariaDB 10.4以降では、rootのデフォルト認証が unix_socket(OSのrootユーザーでのみログイン可)に変わっているケースがあります。mysql -u root -p でエラーになる場合は sudo mysql を試してください。詳しくは後述の「MariaDB 10.5・10.6・11.x で変わったこと」を参照してください。

ユーザー一覧を表示する

1. mysql.userテーブルからユーザーを確認

# MySQL 5.7以降 / MariaDB 10.4以降 mysql> SELECT User, Host FROM mysql.user; +-----------+-----------+ | User | Host | +-----------+-----------+ | root | localhost | | webapp | % | | readonly | 10.0.0.% | +-----------+-----------+

User列:ユーザー名
Host列:接続を許可するホスト。%は全ホスト、localhostはローカルのみ、10.0.0.%はサブネット単位での許可

※ MySQL 5.6以前では SELECT User, Host, Password FROM mysql.user; でパスワードハッシュも確認できましたが、MySQL 5.7以降ではPassword列が authentication_string に変更されています。

ユーザーの権限を確認する

1. SHOW GRANTSで権限を表示

# 特定ユーザーの権限を表示 mysql> SHOW GRANTS FOR 'webapp'@'%'; +-----------------------------------------------------+ | Grants for webapp@% | +-----------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE, DELETE ON `mydb`.* ... | +-----------------------------------------------------+

2. 自分自身の権限を確認

# 現在のユーザーの権限を確認 mysql> SHOW GRANTS;

ユーザーの作成と権限付与

1. ユーザーを作成する

# ローカルホストからのみ接続可能なユーザーを作成 mysql> CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password123'; # 全ホストから接続可能なユーザーを作成 mysql> CREATE USER 'newuser'@'%' IDENTIFIED BY 'password123'; # 特定IPからのみ接続可能なユーザーを作成(アプリサーバーのIPを指定) mysql> CREATE USER 'newuser'@'192.168.1.10' IDENTIFIED BY 'password123';

アプリサーバーのIPが固定されているなら '%'(全ホスト許可)より特定IPを指定するほうがセキュリティ上安全です。

2. 権限を付与する

# 特定データベースの全権限を付与 mysql> GRANT ALL PRIVILEGES ON mydb.* TO 'newuser'@'localhost'; # SELECT権限のみ付与(読み取り専用ユーザー) mysql> GRANT SELECT ON mydb.* TO 'readonly'@'10.0.0.%'; # 付与された内容をその場で確認する mysql> SHOW GRANTS FOR 'readonly'@'10.0.0.%';

FLUSH PRIVILEGES は要りません:GRANTREVOKECREATE USERALTER USERDROP USERSET PASSWORD を実行したときは、サーバーがメモリ上の権限テーブルもその場で読み直します。FLUSH PRIVILEGES が必要になるのは、mysql.user などの権限テーブルを INSERTUPDATEDELETE で直接書き換えたときだけです。
いつから効くかは、付けた範囲で変わります:上の例のようにデータベース単位(ON mydb.*)で付けた権限は、相手のセッションが次に USE mydb を実行したときから効きます。すでにそのデータベースを開いたままつないでいる人には、USE を打ち直すか、つなぎ直してもらってください。テーブル単位・カラム単位で付けた権限は、次のクエリからすぐ効きます。ON *.* で付けたグローバル権限は、SELECTPROCESS のような従来からある権限(静的権限)の場合、つながっているセッションには反映されず次の接続から効きます。MySQL 8.0で追加された動的権限(BACKUP_ADMIN など)は、つないだままでもすぐ効きます。範囲の書き分けは後述の「権限を付与する範囲の決め方」で扱います。
最小権限の原則:アプリ用ユーザーに ALL PRIVILEGES を与えると、SQLインジェクション時の被害が最大化します。読み取りだけなら GRANT SELECT、書き込みが必要なら SELECT, INSERT, UPDATE, DELETE と必要最小限に絞ることを推奨します。

3. ユーザーを削除する

# ユーザーを削除 mysql> DROP USER 'newuser'@'localhost';

ユーザー作成でホストの指定を間違えたときに起きること|IPv6(::1)表記と「作ったのにつながらない」

CREATE USER は通ったのに、作ったはずのユーザーでログインできない。ユーザー作成でいちばん多い詰まりがこれです。原因のほとんどは、ホスト部(@ の右側)の書き方が実際の接続元と噛み合っていないことにあります。MySQLもMariaDBも、ユーザー名とホスト部の組で1つのアカウントとして数えます。名前が同じでもホスト部が違えば、別のアカウントです。

1. IPv6で接続する環境のホスト指定

ホスト部にはIPv4アドレスだけでなく、IPv6アドレスもそのまま書けます。::1 はIPv6のループバックで、IPv4の 127.0.0.1 にあたるアドレスです。

# IPv6のループバックから接続するアカウントを作る mysql> CREATE USER 'ipv6user'@'::1' IDENTIFIED BY 'ipv6pass'; # IPv6アドレスの範囲を許可する(% はLIKEと同じパターン照合) mysql> CREATE USER 'webapp'@'2001:db8::%' IDENTIFIED BY 'password123'; # ネットマスク表記・CIDR表記が使えるのはIPv4だけ mysql> CREATE USER 'webapp'@'10.0.0.0/255.255.255.0' IDENTIFIED BY 'password123'; mysql> CREATE USER 'webapp'@'10.0.0.0/24' IDENTIFIED BY 'password123';

IPv6にネットマスクは書けません:MySQLのマニュアルは「ネットマスク表記はIPv6アドレスには使えない」と明記しています。MariaDBのマニュアルにも同じ記載があります。IPv6で範囲をまとめて許可したいときは、上の '2001:db8::%' のようにパターンで書いてください
CIDR表記が使えるのはMySQL 8.0.23以降です:'10.0.0.0/24' のように書けるようになったのはMySQL 8.0.23からで、それより前は '10.0.0.0/255.255.255.0' の形で書きます。MariaDBのマニュアルはネットマスクを書く形だけを載せています(2026年8月時点のMariaDB公式ドキュメント CREATE USER のページで確認)
ホスト部の % は非推奨になりました:MySQLはバージョン8.0.35から、ホスト部の %_ を非推奨(将来のバージョンで削除される可能性がある)としています。ただしIPv6にはネットマスクもCIDRも使えないため、範囲でまとめる手段は上のパターン指定しか残りません。IPv6で範囲を許可する必要があるときだけこの形を使い、それ以外は接続元を1件ずつ書いてください(IPv4ならネットマスクやCIDRでも書けます)。MariaDBのマニュアルは同じ箇所でワイルドカードを使えると書くだけで、非推奨とは書いていません(2026年8月時点のMariaDB公式ドキュメント CREATE USER のページで確認)
サーバー側がIPv6で待っているかも見ます:::1 で接続するには、サーバーがIPv6で待ち受けている必要があります。MySQLの bind_address は既定値が * で、IPv4とIPv6の両方で待ちます。MariaDBは既定で全アドレスを待ちますが、:: を明示した場合はMariaDB 10.6.0以降IPv6だけを指す挙動に変わっています

2. localhost と 127.0.0.1 と ::1 は、それぞれ別のアカウント

同じマシンの中で接続していても、コマンドの書き方によって当たるアカウントが変わることがあります。後述の「よくあるエラーと対処法」でも 'newuser'@'localhost''newuser'@'127.0.0.1' の取り違えに触れていますが、この2つが別扱いになる理由は接続の種類にあります。

# ソケット接続(-h を付けない、または -h localhost) $ mysql -u newuser -p # TCP接続(IPv4のループバック) $ mysql -h 127.0.0.1 -u newuser -p # TCP接続(IPv6のループバック) $ mysql -h ::1 -u newuser -p # localhost と書いてもTCPで接続する(どのアカウントに当たるかは後述の SELECT USER() で確かめる) $ mysql -h localhost --protocol=TCP -u newuser -p

MySQLのマニュアルは、TCP以外の接続(ソケットファイルなど)はローカル接続として扱われ、ホスト部が localhost のアカウントに一致すると書いています。MariaDBのマニュアルはさらに踏み込んで、Linuxではループバック(127.0.0.1)はローカル接続とみなされないため localhost には一致しないと明記しています。これは認証方式の話ではなく、どのアカウントに当たるかの話です。
実務で効いてくるのは、アプリの接続先をホスト名で書いている場合です。その名前がIPv6のAAAAレコードとIPv4のAレコードの両方を持っていると、クライアント側の解決順によってIPv6で接続され、'app'@'127.0.0.1' しか作っていないアカウントには当たりません。アプリが実際に使う接続の形(ソケットか、IPv4か、IPv6か)に合わせてホスト部を決めるか、必要な形を並べて複数作ってください。

3. つながらないときに見る順番

# 1. サーバーがどのホストとして扱ったかは、エラー文の @ の右側に出る $ mysql -h ::1 -u newuser -p ERROR 1045 (28000): Access denied for user 'newuser'@'::1' (using password: YES) # 2. そのユーザー名で作ってあるホスト部を並べ、上のホストと突き合わせる mysql> SELECT User, Host FROM mysql.user WHERE User = 'newuser'; +---------+-----------+ | User | Host | +---------+-----------+ | newuser | localhost | +---------+-----------+ # 3. 接続できたら、どこから接続したことになっているかを見る mysql> SELECT USER(); +-------------+ | USER() | +-------------+ | newuser@::1 | +-------------+ # 4. 接続の種類(ソケットかTCPか)は STATUS で分かる mysql> STATUS ... Connection: ::1 via TCP/IP ...

ERROR 1045@ の右側を読みます:このエラーの書式は Access denied for user '%s'@'%s' (using password: %s) で、右側にはサーバーが判定に使ったホストが入ります。ここに ::1 と出ていれば、IPv4のアドレスで作ったアカウントは当たりません。なお、同じ ERROR 1045 でも root でパスワードが通らない場合は原因が別にあり、後述の「よくあるエラーと対処法」で扱っています
ユーザー名が出ないときはホストごと弾かれています:ERROR 1130 (HY000): Host '192.168.1.10' is not allowed to connect to this MariaDB server(MySQLでは末尾が this MySQL server)は、接続元のホストが許可されていないときのエラーです。ユーザー名が出ないところが1045との違いで、パスワードを疑う前にホスト部を確認してください
名前解決を切ったサーバーではホスト名指定が当たりません:MySQLのマニュアルは、skip_name_resolve を有効にするとサーバーはIPアドレスだけで照合し、IPアドレスで指定したアカウントしか使えないと書いています。'app'@'db-front01' のようにホスト名で作ったアカウントは、この設定のサーバーでは当たりません。ソケット接続がローカル接続として localhost のアカウントに一致するのは名前解決とは別の判定なので、'app'@'localhost' はこの設定でも当たります
接続できてデータベースだけ見えないときは原因が違います:その場合に出るのは ERROR 1045 ではなく ERROR 1044 で、権限の側の問題です。後述の「よくあるエラーと対処法」を見てください

権限を付与する範囲の決め方|グローバル・データベース・テーブル・カラムの4段階

「mysql 権限 付与」で調べると GRANT ALL PRIVILEGES ON mydb.* TO ... の一行だけが出てきますが、現場で効いてくるのは ON の後ろの書き方です。ここを一段広く書いてしまうと、アプリ用のアカウントが同じサーバーに同居している別案件のデータベースまで読める状態になります。

1. ON の書き方で、権限が効く範囲が決まる

# グローバル:このサーバーの全データベースに効く mysql> GRANT SELECT ON *.* TO 'audit'@'10.0.0.%'; # データベース単位:mydb の中の全テーブルに効く mysql> GRANT SELECT ON mydb.* TO 'readonly'@'10.0.0.%'; # テーブル単位:mydb の orders テーブルだけに効く mysql> GRANT SELECT ON mydb.orders TO 'readonly'@'10.0.0.%'; # カラム単位:mydb.members の id と name の2列だけ読める mysql> GRANT SELECT (id, name) ON mydb.members TO 'readonly'@'10.0.0.%';

グローバル(*.*):サーバー全体を見る権限(PROCESSRELOADSHOW DATABASES など)はここでしか付きません。逆にアプリ用アカウントへ SELECT ON *.* を付けると、同じMySQLに載っている他システムのデータベースも、これから追加されるデータベースも、まとめて読めるようになります
データベース単位(mydb.*):アプリ用アカウントの基本形。1アプリにつき1データベース1アカウントで揃えておくと、あとで棚卸しが楽になります
テーブル単位(mydb.orders):集計バッチや外部連携のように、読む対象が決まっているアカウント向け
カラム単位((id, name)):列名をカッコで囲んで指定します。カラム単位で書けるのは SELECTINSERTUPDATEREFERENCES の4つで、DELETE は行ごと消す操作なので列を絞れません。会員テーブルのうちメールアドレスと電話番号は見せない、といった使い方をします

MySQL 8.0以降は GRANT でアカウントを作れなくなりました。存在しないアカウントへ GRANT すると ERROR 1410 (42000): You are not allowed to create a user with GRANT で止まります。MariaDBは今も GRANT ... IDENTIFIED BY 'パスワード' と書けばアカウントごと作りますが、パスワードを書かないと ERROR 1133 で止まります(MariaDB 10.1.7以降の既定設定)。どちらの環境でも、先に CREATE USER でアカウントを作ってから GRANT する手順に揃えておくと迷いません。

2. 範囲は足し算になる|下の段だけ取り消しても消えない

サーバーは グローバル → データベース → テーブル → カラム の順に権限を見て、どこか一段でも許可があればその操作を通します。MySQLの公式マニュアルでも、判定は「グローバル権限 または データベース権限 または テーブル権限 または カラム権限 または ルーチン権限」と説明されています。最後のルーチン権限はストアドプロシージャ・ストアドファンクション専用の段で、テーブルの読み書きには関係しません。

この足し算が、権限を剥がすときに引っかかるところです。

# まず今どうなっているかを見る mysql> SHOW GRANTS FOR 'webapp'@'%'; +---------------------------------------------------+ | Grants for webapp@% | +---------------------------------------------------+ | GRANT SELECT ON *.* TO `webapp`@`%` | | GRANT SELECT, INSERT ON `mydb`.* TO `webapp`@`%` | +---------------------------------------------------+

この状態で REVOKE SELECT ON mydb.* FROM 'webapp'@'%'; を実行しても、消えるのは2行目の mydb 側だけです。1行目の ON *.*SELECT は残るので、webapp は引き続き全データベースを読めます。

取り消すときの注意:SHOW GRANTS の出力に出ている ON の書き方をそのまま写して REVOKE を書いてください。付けたときと違う範囲を指定した REVOKE は、権限を残したままエラーで終わります。

3. REVOKEで権限を取り消す(アカウント自体は残る)

# 付けたときと同じ範囲を指定して取り消す mysql> REVOKE SELECT ON mydb.* FROM 'readonly'@'10.0.0.%'; # そのアカウントの権限を全部落とす(他人へ権限を配る権限も含めて) mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'readonly'@'10.0.0.%'; # 結果を確認する mysql> SHOW GRANTS FOR 'readonly'@'10.0.0.%'; +--------------------------------------------------+ | Grants for readonly@10.0.0.% | +--------------------------------------------------+ | GRANT USAGE ON *.* TO `readonly`@`10.0.0.%` | +--------------------------------------------------+

REVOKE ALL PRIVILEGES, GRANT OPTION は、そのアカウントに直接付けたグローバル・データベース・テーブル・カラム・ルーチンの権限をまとめて落とします。実行後に残る USAGE は「権限なし」を表す印で、ログインはできるが何もできない状態です。SHOW GRANTS の出力が空にならないため消し損ねたように見えますが、直接付けた権限はこれでゼロです。

ロールを使っている場合は、この文ではロールが外れません。ロール側に付いている権限は残るので、SHOW GRANTS の出力に、権限名ではなくロール名が書かれた GRANT `ロール名`@`%` TO `ユーザー`@`ホスト` のような行が無いか見てください。あれば REVOKE 'ロール名'@'%' FROM 'ユーザー'@'ホスト'; で別に外します。

REVOKE が落とすのは権限だけで、アカウントは mysql.user に残ります。アカウントごと消すのは DROP USER です。退職者や使われていないアカウントを整理するときは、いきなり DROP USER せず、まず REVOKE ALL PRIVILEGES, GRANT OPTION で権限だけ落として数日動かしてください。止まっていたはずの夜間バッチが古いアカウントを使っていた、という取りこぼしを、接続エラーの形で先に拾えます。

4. WITH GRANT OPTIONは「自分の権限を他人へ配れる」権限

# このアカウントは、自分が持つ SELECT を他のアカウントへ配れるようになる mysql> GRANT SELECT ON mydb.* TO 'dba_sub'@'10.0.0.%' WITH GRANT OPTION; # 配る権限だけを取り上げる mysql> REVOKE GRANT OPTION ON mydb.* FROM 'dba_sub'@'10.0.0.%';

WITH GRANT OPTION が与えるのは、自分がその範囲で持っている権限を、他のアカウントへ付け直せるという権限です。自分が持っていない権限は配れません。またこれだけではアカウントを作れません(アカウントの作成には CREATE USER 権限か mysql スキーマへの INSERT 権限が別に要ります)。

それでもアプリ用アカウントに付けるべきではありません。アプリにSQLインジェクションの穴があると、攻撃者はそのアカウントが持っている権限を、サーバーにすでに存在する別のアカウント(放置された作業用アカウントや、初期状態のまま残っている匿名アカウント)へ配れます。こちらがアプリ用アカウントのパスワードを変えても、配られた先の権限は残ったままです。付けてよいのは、データベースの運用を分担していて、権限を配る作業を実際に任せている担当者のアカウントに限ってください。

MariaDBでの操作

RHEL/CentOS 7以降では、MySQLの代わりにMariaDBがデフォルトで採用されています。ユーザー管理のSQL文はほぼ同じですが、認証方式に違いがある場合があります。

# MariaDBにログイン $ mysql -u root -p # MariaDBのバージョン確認 mysql> SELECT VERSION(); # ユーザー一覧(MariaDBでも同じSQL) mysql> SELECT User, Host FROM mysql.user;

MySQLを終了する

mysql> quit Bye

よくあるエラーと対処法

ERROR 1045: Access denied for user 'root'@'localhost'

rootパスワードを設定したにもかかわらず接続できない場合は、MariaDB 10.4以降で有効になった unix_socket 認証が原因であるケースが多いです。

# sudo経由でパスワードなしで接続(unix_socket認証の場合はこれで入れる) $ sudo mysql -u root # 認証プラグインを確認 MariaDB [(none)]> SELECT User, Host, plugin FROM mysql.user WHERE User='root'; +------+-----------+-------------+ | User | Host | plugin | +------+-----------+-------------+ | root | localhost | unix_socket | +------+-----------+-------------+ # パスワード認証に切り替える MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword!';

ERROR 2003: Can't connect to MySQL server (111 Connection refused)

リモートから接続が拒否された場合は、以下を順番に確認してください。
MariaDB/MySQLが起動しているか:systemctl status mariadb(または mysqld)で確認
bind-addressが変更されているか:ss -tlnp | grep 3306 で0.0.0.0バインドを確認
firewalldがブロックしていないか:firewall-cmd --list-services でmysqlが含まれているか確認
ユーザーのHostが一致しているか:接続元IPと CREATE USER のHost部分が一致しているか確認

ERROR 1044: Access denied for user 'xxx'@'localhost' to database 'yyy'

接続したアカウントに、そのデータベースへの権限が付いていないときに出ます。FLUSH PRIVILEGES の実行し忘れではありません(GRANT はその場で反映されます)。原因は次の3つのどれかです。
権限そのものが無い:GRANT をまだ実行していない、または対象のデータベース名を打ち間違えている
ユーザー名・ホストの取り違え:'newuser'@'localhost' に付けたのに 'newuser'@'127.0.0.1' で接続している。MySQLはこの2つを別のアカウントとして扱います
付けた範囲が違う:テーブル単位で付けたのにデータベース全体を触ろうとしている(範囲の考え方は前述の「権限を付与する範囲の決め方」を参照)

# 今つながっているアカウントを確かめる mysql> SELECT CURRENT_USER(); +----------------------+ | CURRENT_USER() | +----------------------+ | newuser@localhost | +----------------------+ # そのアカウントの権限を確認する mysql> SHOW GRANTS; # 権限が付いていなければ、範囲を指定して付け直す mysql> GRANT ALL PRIVILEGES ON mydb.* TO 'newuser'@'localhost';

SELECT CURRENT_USER() を先に打つのは、接続時に実際に採用されたアカウントを確かめるためです。'newuser'@'%' のようにホスト部をワイルドカードで作ったアカウントは、localhost からつなぐと、初期状態のまま残っている匿名アカウント(''@'localhost')のほうが先に一致します。ホストの指定が細かいほうが優先されるためで、このとき CURRENT_USER() の表示は @localhost になります。上の例のように 'newuser'@'localhost' で作っていれば、この取り違えは起きません。

本記事のまとめ

やりたいこと コマンド
MySQLにログイン mysql -u root -p
ユーザー一覧を表示 SELECT User, Host FROM mysql.user;
ユーザーの権限を確認 SHOW GRANTS FOR 'ユーザー'@'ホスト';
ユーザーを作成 CREATE USER 'ユーザー'@'ホスト' IDENTIFIED BY 'パスワード';
権限を付与 GRANT ALL PRIVILEGES ON DB名.* TO 'ユーザー'@'ホスト';
権限を取り消す REVOKE SELECT ON DB名.* FROM 'ユーザー'@'ホスト';
権限を全部落とす(アカウントは残す) REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'ユーザー'@'ホスト';
権限テーブルを直接書き換えた後に反映 FLUSH PRIVILEGES;
ユーザーを削除 DROP USER 'ユーザー'@'ホスト';

「show users」と検索する人へ:MySQLにこのコマンドはない

PostgreSQLには \du、Oracleには SELECT * FROM dba_users という直感的なコマンドがあるため、MySQLにも SHOW USERS があると思って検索する方がたくさんいます。実際には、MySQL / MariaDBに「SHOW USERS」というSQL文は存在しません。

# こう打つと文法エラーになる mysql> SHOW USERS; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USERS' at line 1

正しいユーザ一覧の取り方は、ここまでで紹介した SELECT User, Host FROM mysql.user; です。

1. 「ユーザー一覧」「ユーザ一覧」「user list」全部このSQLで取れる

表記揺れに惑わされる必要はありません。MySQL / MariaDBにおける「ユーザ一覧」「ユーザー一覧」「ユーザー確認」「user list」「ユーザ確認」は、すべて以下の1行で取得できます。

# どの検索クエリで来た人も、答えはこれ1本 mysql> SELECT User, Host FROM mysql.user;

追加でログインアカウント名と認証プラグインも見たいときは、列を増やします。

# 認証方式(plugin列)まで見る mysql> SELECT User, Host, plugin FROM mysql.user; +-----------+-----------+-----------------------+ | User | Host | plugin | +-----------+-----------+-----------------------+ | root | localhost | mysql_native_password | | webapp | % | caching_sha2_password | | readonly | 10.0.0.% | mysql_native_password | +-----------+-----------+-----------------------+

plugin列を見ると、各ユーザがどの認証方式(パスワードチェック方式)を使っているかが分かります。MySQL 8.0以降のデフォルトは caching_sha2_password、MariaDB 10.4以降は mysql_native_password が混在することが多いです。

2. 「show grants」を全ユーザに対して実行する

「特定ユーザの権限確認は SHOW GRANTS FOR …」と説明しましたが、「全ユーザの権限を一括で見たい」というニーズもよくあります。MySQLには一括版のコマンドはないので、シェルで回します。

# 全ユーザの権限を一括表示するシェル版(root権限で実行) $ mysql -u root -p -BNe \ "SELECT CONCAT('SHOW GRANTS FOR \'\'\'', User, '\'\'\'@\'\'\'', Host, '\'\'\'\';') \ FROM mysql.user" | \ mysql -u root -p

show grants」「mysql 権限確認」で検索する読者の本当の意図はここにあるケースが多いです。1ユーザずつ手打ちで SHOW GRANTS FOR を実行するのは現実的ではないため、運用ではこの一括スクリプトを使ってください。

3. 情報スキーマ経由でも同じ情報が取れる

MySQL 8.0以降では、INFORMATION_SCHEMA.USER_PRIVILEGESSCHEMA_PRIVILEGES から権限情報を取得できます。

# グローバル権限を取得(INFORMATION_SCHEMA経由) mysql> SELECT GRANTEE, PRIVILEGE_TYPE, IS_GRANTABLE FROM INFORMATION_SCHEMA.USER_PRIVILEGES; +----------------+----------------+--------------+ | GRANTEE | PRIVILEGE_TYPE | IS_GRANTABLE | +----------------+----------------+--------------+ | 'root'@'localhost' | SELECT | YES | | 'webapp'@'%' | SELECT | NO | +----------------+----------------+--------------+

mysql.user テーブルを直接読むよりも、INFORMATION_SCHEMA 経由のほうがバージョン差異の影響を受けにくく、自動化スクリプトには向いています。

MariaDB 10.5・10.6・11.x で変わったこと(2026年版)

2026年現在、RHEL 9 / Rocky Linux 9 / AlmaLinux 9 系には MariaDB 10.5、Ubuntu 22.04 LTS には MariaDB 10.6、Ubuntu 24.04 LTS には MariaDB 10.11、最新ディストリでは MariaDB 11.x が同梱されています。MySQL の代わりに MariaDB を使うサーバーが増えたため、ユーザ確認まわりで「以前と違う」と感じる点が出てきました。

まず、つないだ先が MariaDB か MySQL かを確かめてください:ここから先の話は、どちらを使っているかで変わります。見分けは SELECT VERSION(); の出力で付きます。

# MariaDBなら、バージョン番号のあとに -MariaDB が入る mysql> SELECT VERSION(); +------------------+ | VERSION() | +------------------+ | 10.11.14-MariaDB | +------------------+

MySQLの場合は 8.0.36 のようにバージョン番号だけが返り、-MariaDB は入りません。バイナリログや slow log を有効にしたサーバーでは 10.11.14-MariaDB-log のように後ろにも続きが付きますが、-MariaDB が入っていれば MariaDB です。
プロセス名とコマンド名も変わっています:MariaDB 10.5 で、mysql で始まっていたバイナリが mariadb で始まる名前に変わり、旧名のほうが新しいバイナリへのシンボリックリンクになりました。サーバーの実体は mariadbd、コマンドラインクライアントの実体は mariadb です。ps の出力に mysqld ではなく mariadbd と出るのはこのためで、異常ではありません。ただし MariaDB 11.0 以降は、この mysql 側のリンクが mariadb-client-compat のような別パッケージへ分けられました。mysql で「コマンドが見つからない」と出たら、mariadb のほうで叩いてください。

1. SHOW CREATE USER で「実際に発行された CREATE 文」を再現できる

MariaDB 10.4 以降 / MySQL 8.0 以降では、SHOW CREATE USER でユーザの作成時のSQL文を再構成できます。バックアップ・移行時に重宝します。

mysql> SHOW CREATE USER 'webapp'@'%'; +----------------------------------------------------------------+ | CREATE USER for webapp@% | +----------------------------------------------------------------+ | CREATE USER 'webapp'@'%' IDENTIFIED VIA mysql_native_password USING '*ABCDEF...'; | +----------------------------------------------------------------+

このコマンドで得たSQL文を別のサーバで実行すれば、同じユーザを同じパスワードハッシュで再現できます。

2. unix_socket 認証(パスワードを使わない root ログイン)

MariaDB 10.4 以降のディストリ標準パッケージでは、rootユーザのデフォルト認証が unix_socket(OSのrootユーザでのみログイン可)に変わっています。「mysql -u root -p」でパスワードを聞かれず、いきなり通る/通らないの違いがここに起因します。

# OSのrootから(パスワードなしでログイン可) [root@db01 ~]# mysql MariaDB [(none)]> SELECT User, Host, plugin FROM mysql.user WHERE User='root'; +------+-----------+-------------+ | User | Host | plugin | +------+-----------+-------------+ | root | localhost | unix_socket | +------+-----------+-------------+ # 一般ユーザから(パスワード認証に切り替えたい場合) $ mysql -u root -p ERROR 1698 (28000): Access denied for user 'root'@'localhost'

パスワード認証に戻したい場合は、rootユーザのpluginを mysql_native_password に変更します。

# OSのrootからログインして変更 MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('your_password');

3. MariaDB 11.x 以降の主な変化(運用視点)

MariaDB 11.0 ~ 11.4 で、MySQLとの差異がさらに広がっています。ユーザ管理関連で覚えておきたいポイントを整理します。

項目 MariaDB 11.x の挙動
デフォルト認証プラグイン mysql_native_password(互換性重視)。MySQL 8.0+ は caching_sha2_password
ROLE(ロール) MariaDB 10.0以降サポート。CREATE ROLEでロール作成、GRANTで割り当て
SHOW USERSの代替 MariaDB独自の mysql.global_priv テーブル(10.4以降)も併用可
passwordless root 11.x でも unix_socket がデフォルトのまま

4. MariaDB 10.4+ で global_priv テーブルから一覧を取る

MariaDB 10.4 以降では、mysql.user はビュー扱いになり、実体は mysql.global_priv テーブルにあります。SHOW CREATE TABLE mysql.user を見ると確認できます。MariaDB固有の機能(パスワード有効期限・パスワード履歴など)はこちらに格納されています。

# MariaDB 10.4+ で実体テーブルを直接見る MariaDB [(none)]> SELECT User, Host, JSON_DETAILED(Priv) FROM mysql.global_priv;

ただし運用上は、互換性のある SELECT User, Host FROM mysql.user; を使い続けるのが安全です。global_priv はMariaDB固有のため、MySQLに移行する可能性がある環境では避けてください。

5. MariaDBバージョン早見表(2026年8月時点)

ユーザ管理で迷ったら、まず自サーバのバージョンを確認します。

ディストリ 同梱DB 確認コマンド
RHEL 9 / Rocky 9 / AlmaLinux 9 MariaDB 10.5 mysql --version または SELECT VERSION();
RHEL 10 / Rocky 10 MariaDB 10.11 SELECT VERSION();
Ubuntu 22.04 LTS MariaDB 10.6 SELECT VERSION();
Ubuntu 24.04 LTS MariaDB 10.11 SELECT VERSION();
Ubuntu 26.04 LTS MariaDB 11.8 SELECT VERSION();
MariaDB公式リポジトリ MariaDB 12.3 LTS(2026-) SELECT VERSION();

本家のサポート期限も見ておいてください:MariaDB本家のコミュニティ版サポートは、上の表にある 10.5 が2025年6月24日、10.6 が2026年7月6日で終わっています。10.11 は2028年2月16日、11.4 は2029年5月29日、11.8 は2028年6月4日、12.3 は2029年6月12日まで続きます。版が新しいほど期限が後ろになるとは限りません。11.4 までは5年、11.8 以降は3年と、保守期間そのものが変わったためです。ただしディストリ同梱版は、ディストリ側が自社のサポート期間の中で修正を取り込みます。本家の期限を過ぎていても、OSのサポートが続いていれば修正は届きます。同梱版を使っている場合は、本家の日付ではなくOSのサポート情報のほうで確認してください。本家のリポジトリを直接入れていて、期限の切れた 10.5 や 10.6 のままなら、LTS系列を乗り換える時期です。12.3 系へ上げるかどうかの判断材料は MariaDB 12.3.2 LTSリリース|既存系列からの移行判断 にまとめています。
※最終更新: 2026-08-13(早見表にUbuntu 26.04 LTSを追加・公式リポジトリ行を12.3 LTSへ更新・本家のサポート期限・MariaDBとMySQLの見分け方を追加)/2026-05-11(show users代替・全ユーザ一括grants・MariaDB 10.5/10.6/11.x対応・unix_socket認証を追加)

mysql.user テーブルから authentication_string を含めてユーザー詳細を取得する|権限とパスワードハッシュの一括確認

「MySQL ユーザー一覧」で辿り着く方の多くは、User と Host だけでは足りず、パスワードのハッシュと付与済みの権限まで一括で確認したいケースだと思います。mysql.user テーブルを直接 SELECT すれば、グローバル権限の Y/N、認証プラグイン、パスワードハッシュまで一発で取れます。

# ユーザー / ホスト / 認証プラグイン / パスワードハッシュをまとめて取得
mysql> SELECT User, Host, plugin, authentication_string
    -> FROM mysql.user
    -> ORDER BY User, Host;
+------------------+-----------+-----------------------+-------------------------------------------+
| User             | Host      | plugin                | authentication_string                     |
+------------------+-----------+-----------------------+-------------------------------------------+
| app_user         | %         | mysql_native_password | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root             | localhost | caching_sha2_password | $A$005$...                                |
+------------------+-----------+-----------------------+-------------------------------------------+

付与済みのデータベース単位の権限を一覧で見たいなら mysql.db も併用します。

# データベース単位の付与状況を確認
mysql> SELECT Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv
    -> FROM mysql.db
    -> WHERE User = 'app_user';

私もアカウント棚卸しのときに SHOW GRANTS を1ユーザーずつ叩いていた時期があり、20アカウントを超えた瞬間に手が動かなくなりました。mysql.usermysql.db を SELECT する方法を覚えると、Excel に貼り付けて棚卸し表を作るのも楽になります。

# SHOW GRANTS を全ユーザー分まとめて生成するワンライナー
mysql> SELECT CONCAT('SHOW GRANTS FOR \'\'\'', User, '\'\'\'@\'\'\'', Host, '\'\'\';') AS query
    -> FROM mysql.user;

MySQLのユーザー管理をもっと深く学びたい方へ

権限設定を誤るとデータベース全体がセキュリティリスクにさらされます。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

<PR>手元に置いて学びを深める1冊

MySQL徹底入門 第4版 MySQL 8.0対応

まず無料メルマガでLinux運用の型を学ぶのが第一歩、加えてMySQLのユーザー管理・権限設計を体系的に押さえたいなら本書。日本MySQLユーザ会メンバーによる定番の解説書で、権限やレプリケーションまで実務目線でカバーしています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。