文章目录
- MySQL用户管理从入门到不翻车:别再裸奔用root了!
-
- 一、先翻户口本:MySQL用户存在哪?
- 二、host字段全解析:不止localhost,还有这些玩法
-
- [1. host取值对照表](#1. host取值对照表)
- [2. 新手最懵:localhost ≠ 127.0.0.1](#2. 新手最懵:localhost ≠ 127.0.0.1)
- [3. 实操:创建不同host的用户](#3. 实操:创建不同host的用户)
- [4. 高危账号整改示例](#4. 高危账号整改示例)
- 三、用户账号的"生老病死":增删改全套操作
-
- [1. 新建用户:给新人办门禁卡](#1. 新建用户:给新人办门禁卡)
-
- [🚧 初学者必踩坑:密码太简单报错](#🚧 初学者必踩坑:密码太简单报错)
- [🚨 红线警告:别图省事写 `@'%'`](#🚨 红线警告:别图省事写
@'%')
- [2. 删除用户:销户要带完整信息](#2. 删除用户:销户要带完整信息)
- [3. 修改密码:换锁操作](#3. 修改密码:换锁操作)
- 四、权限才是核心:给你开门但不给你开保险柜
- 五、远程连接终极避坑:90%的人都搞错过IP
-
- [1. 灵魂对比:两个IP完全不是一回事](#1. 灵魂对比:两个IP完全不是一回事)
- [2. 生活化例子帮你记牢](#2. 生活化例子帮你记牢)
- [3. 两个最常见的错误](#3. 两个最常见的错误)
-
- [❌ 错误1:@后面写了服务器自己的IP](#❌ 错误1:@后面写了服务器自己的IP)
- [❌ 错误2:-h后面写了客户端自己的IP](#❌ 错误2:-h后面写了客户端自己的IP)
- [4. 远程连不上?按这个顺序排查](#4. 远程连不上?按这个顺序排查)
- 六、初学者避坑+最佳实践
- 七、总结
MySQL用户管理从入门到不翻车:别再裸奔用root了!
相信很多刚接触MySQL的同学,从安装到写CRUD,全程一把root钥匙走天下------就像小区所有门都用总控钥匙,想进谁家进谁家,想搬啥搬啥。爽是爽了,但凡手滑敲个drop database,或者被外人摸到账号,那就是删库跑路的大型社死现场。
今天咱们就把MySQL的「用户权限体系」扒明白,从账号查询到host限制,再到权限分配和远程连接踩坑,手把手教你给不同人配不同的"门禁卡",从此告别root裸奔。
一、先翻户口本:MySQL用户存在哪?
MySQL不搞黑箱,所有用户信息都明明白白存在系统库mysql的user表里------这就是MySQL的「户籍登记簿」。
先登进去查一下家底:
sql
-- 切换到系统库
use mysql;
-- 查看所有用户的核心信息
select User, Host from user;
真实查询输出示例
你执行后会看到类似这样的结果:
| User | Host |
|---|---|
| zhangsan | % |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
逐行解读你的「户口本」
-
zhangsan|%这是你自己创建的自定义账号,格式为
'zhangsan'@'%'。%是通配符,代表允许从任意IP地址登录。- 只要知道密码,全世界任何一台机器都能远程连接你的数据库。
- ⚠️ 高危预警:这就是典型的"门户大开"配置,学习测试玩玩可以,生产环境绝对禁止。
-
mysql.session|localhostMySQL 内置系统账号,供 MySQL 内部进程通信使用。
- 不要删除、不要修改密码,否则会导致数据库异常。
-
mysql.sys|localhost系统内置账号,用于
sys系统库的对象访问。- 同样是系统自带账号,别动它就行。
-
root|localhost超级管理员账号,
Host为localhost代表只能从本机登录。- 外部机器无法直接用 root 远程连接,这个配置是安全的默认配置。
💡 最核心的概念:MySQL里的用户是「用户名 + 主机名 」联合唯一的。
也就是说,
'zhangsan'@'localhost'和'zhangsan'@'%'是两个完全不同的账号,密码、权限互不干扰,删的时候也要分开删。
二、host字段全解析:不止localhost,还有这些玩法
host字段用来限制"谁能来连这个数据库",可以精准到一台机器,也可以放宽到一个网段,甚至全开。
1. host取值对照表
| host取值 | 含义 | 安全等级 | 适用场景 |
|---|---|---|---|
localhost |
本机Socket连接,Linux下走mysql.sock套接字文件,不走TCP网络 |
✅ 最高安全 | 本机服务、本地调试 |
127.0.0.1 |
本机TCP回环地址,走3306端口网络连接 | ✅ 极高安全 | 本机通过TCP方式连接 |
192.168.1.100 |
只允许这一个固定IP的机器远程连接 | ✅ 推荐生产用 | 指定的开发机、应用服务器 |
192.168.1.% |
允许整个192.168.1.x局域网网段连接,%是通配符 |
⚠️ 中等安全 | 公司内网多台机器访问 |
% |
允许任意IP地址连接,全世界只要知道密码就能连 | ❌ 高危 | 仅学习环境演示,生产严禁 |
app01.test.com |
允许该域名解析出的机器登录 | ⚠️ 依赖DNS | 极少使用,不推荐 |
2. 新手最懵:localhost ≠ 127.0.0.1
这是面试高频考点,也是90%的人踩过的坑:
'xxx'@'localhost':走Unix Socket文件,不经过TCP协议,速度更快,但只能本地程序用'xxx'@'127.0.0.1':走TCP/IP协议,访问3306端口,本质是"远程连接自己"
现象验证:
你创建了用户'test'@'localhost',那么:
bash
# ✅ 可以登录(默认走Socket)
mysql -u test -p
# ❌ 报错访问拒绝!因为host不匹配
mysql -h 127.0.0.1 -u test -p
如果希望两种本机方式都能登录,必须创建两个独立账号:
sql
create user 'test'@'localhost' identified by 'Test@123456';
create user 'test'@'127.0.0.1' identified by 'Test@123456';
3. 实操:创建不同host的用户
sql
-- 1. 只允许本机登录
create user 'local_user'@'localhost' identified by 'Local@123';
-- 2. 只允许192.168.1.20这台开发机登录
create user 'dev_user'@'192.168.1.20' identified by 'Dev@123456';
-- 3. 允许整个192.168.1.x网段登录
create user 'lan_user'@'192.168.1.%' identified by 'Lan@123456';
-- 4. 允许任意IP登录(高危!仅演示)
create user 'danger_user'@'%' identified by 'Danger@123456';
4. 高危账号整改示例
针对上面查到的 'zhangsan'@'%' 这种高危账号,推荐两种整改方案:
方案一:直接删除(不需要了就清掉)
sql
drop user 'zhangsan'@'%';
方案二:改成只允许固定IP访问
sql
-- 先删除旧的高危账号
drop user 'zhangsan'@'%';
-- 新建只允许指定IP登录的账号
create user 'zhangsan'@'192.168.1.20' identified by 'ZhangSan@123456';
-- 再授权对应权限
grant select on test_db.* to 'zhangsan'@'192.168.1.20';
三、用户账号的"生老病死":增删改全套操作
1. 新建用户:给新人办门禁卡
基础语法:
sql
create user '用户名'@'登陆主机/ip' identified by '密码';
🚧 初学者必踩坑:密码太简单报错
如果你设密码像123456,大概率会弹这个错:
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
这是MySQL的密码校验插件在干活,嫌你密码太弱。查看当前密码策略:
sql
SHOW VARIABLES LIKE 'validate_password%';
学习环境可以调低策略,生产环境强烈建议老老实实设大小写+数字+特殊符号的复杂密码。
🚨 红线警告:别图省事写 @'%'
很多人嫌麻烦直接写create user 'xxx'@'%',相当于你家门锁是个摆设,全世界只要知道密码就能进。学习环境本机用localhost就够了,真需要远程连接也只授权指定IP。
2. 删除用户:销户要带完整信息
想删用户?千万别图省事只写用户名:
sql
-- 错误示范!大概率报错
drop user dev_user;
-- ERROR 1396 (HY000): Operation DROP USER failed for 'dev_user'@'%'
为啥报错?因为MySQL默认你没写host就是%,但你创建的是@'localhost'的用户,对不上号当然删不掉。
✅ 正确写法,必须带上host:
sql
drop user 'dev_user'@'192.168.1.20';
还是那句话:用户是user+host绑定的,删户也要"精准销户"。
3. 修改密码:换锁操作
分两种场景:自己改自己的,和管理员改别人的。
场景1:自己改自己的密码
登录自己账号后执行:
sql
set password = password('新密码');
场景2:root管理员修改指定用户密码
sql
-- 兼容旧版本写法
set password for 'dev_user'@'192.168.1.20' = password('Dev@654321');
-- MySQL 8.0+ 官方推荐写法
alter user 'dev_user'@'192.168.1.20' identified by 'Dev@654321';
四、权限才是核心:给你开门但不给你开保险柜
用户创建完只是第一步,真正的灵魂操作是权限分配。MySQL的权限粒度细到"能看哪张表、能不能删数据、能不能建库",完全可以做到"张三只能管mytest库,李四只能管msg库"。
1. 常见权限速览
不用全背,按用途分几类就好:
| 权限分类 | 代表权限 | 能干啥 |
|---|---|---|
| 数据读写 | SELECT, INSERT, UPDATE, DELETE | 查、增、改、删表数据 |
| 结构操作 | CREATE, DROP, ALTER, INDEX | 建库/建表、删库/删表、改表结构、建索引 |
| 视图/存储过程 | CREATE VIEW, EXECUTE | 创建视图、执行存储过程 |
| 服务器管理 | CREATE USER, SUPER, SHOW DATABASES | 创建用户、超级管理员权限、查看所有库 |
2. 授权操作:grant 给你发权限
语法模板:
sql
grant 权限列表 on 库.对象名 to '用户名'@'登陆位置';
几个关键说明:
- 权限列表 :多个权限用逗号分隔,比如
select,insert,update all [privileges]:代表赋予该对象上的所有权限- 范围控制 :
*.*= 所有库的所有表(满级权限,别乱给)test_db.*= test_db库下的所有表(最常用)test_db.user_info= 只针对test_db库的user_info表
完整实操示例
- root账号先准备测试库表:
sql
create database if not exists test_db;
use test_db;
create table if not exists user_info (
id int primary key auto_increment,
name varchar(20),
balance decimal(10,2)
);
insert into user_info(name, balance) values
('张三', 100.00),
('李四', 200.00),
('王五', 300.00);
- 给
dev_user开放test_db库的查询权限:
sql
grant select on test_db.* to 'dev_user'@'192.168.1.20';
- 用
dev_user登录验证:
sql
-- 能看到test_db库
show databases;
-- 能查询数据
use test_db;
select * from user_info;
-- ❌ 删除报错,因为没给delete权限
delete from user_info where id = 1;
查看用户有哪些权限
sql
show grants for 'dev_user'@'192.168.1.20';
🧙 生效咒语:flush privileges
有时候赋完权发现没生效?执行一下这句"刷新咒语":
sql
flush privileges;
正常用grant/revoke操作会自动生效,但如果是直接修改mysql.user表的话就必须手动刷新。
3. 回收权限:revoke 把权限收回来
给出去的权限想收回来,用revoke,语法和grant几乎对称:
sql
revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';
比如回收dev_user对test_db的所有权限:
sql
revoke all on test_db.* from 'dev_user'@'192.168.1.20';
回收完用户就又变回"白板"了,但账号还在,不会被删除。
五、远程连接终极避坑:90%的人都搞错过IP
这是初学者问得最多的问题:为什么账号建好了,远程还是连不上?大概率是IP搞反了。
1. 灵魂对比:两个IP完全不是一回事
| 位置 | 填什么IP | 含义 |
|---|---|---|
SQL语句里 'dev'@'192.168.1.20' |
客户端IP | 允许哪台机器来访问;数据库校验:来连接的这台机器是不是这个IP |
连接命令 -h 192.168.1.10 |
服务端IP | 客户端要去找哪一台机器上的MySQL服务 |
2. 生活化例子帮你记牢
- 数据库服务器A(IP:192.168.1.10)= 银行网点
- 你的电脑B(IP:192.168.1.20)= 你本人
'dev'@'192.168.1.20'→ 银行规定:只允许你家这个地址的人进来办业务mysql -h 192.168.1.10 -u dev -p→ 你出门:坐车去银行网点的地址办业务
👉 银行地址(-h)和允许来访的客户地址(@ip),是完全不一样的两个东西!
3. 两个最常见的错误
❌ 错误1:@后面写了服务器自己的IP
sql
-- 错!@后面应该写客户端IP,不是服务器IP
create user 'dev'@'192.168.1.10' identified by 'Dev@123456';
结果:只有服务器自己能连这个账号,其他机器连都报访问拒绝。
❌ 错误2:-h后面写了客户端自己的IP
bash
# 错!-h应该写数据库服务器IP,不是你自己电脑IP
mysql -h 192.168.1.20 -u dev -p
结果:在你自己电脑上找MySQL服务,当然找不到,直接连接超时。
4. 远程连不上?按这个顺序排查
- 账号host对不对:确认@后面的IP是你客户端的真实IP
- MySQL监听地址 :服务器配置文件
my.cnf里,bind-address要设为0.0.0.0(或注释掉),不能只写127.0.0.1 - 防火墙:服务器防火墙要放行3306端口
- 网络连通性 :客户端先执行
ping 服务器IP测试网络通不通,再用telnet 服务器IP 3306测试端口通不通
六、初学者避坑+最佳实践
-
最小权限原则
给用户刚好够用的权限就行。比如开发人员只给
select,insert,update,别一上来就grant all,更别随便给*.*权限。 -
host字段尽量收敛
能写固定IP绝不写网段,能写网段绝不写
%;本机用localhost,远程只授权指定服务器IP。 -
删用户一定要带host
永远别写
drop user xxx;,一定要写全'user'@'host',避免删错账号。 -
账号定期审计
隔段时间查一下
mysql.user表,看看有没有不用的僵尸账号,特别是host为%的账号,及时清理。 -
密码和连接安全
生产环境禁用弱密码,不要把密码硬编码在代码里;远程连接尽量走内网,不要把3306端口暴露在公网。
七、总结
MySQL用户管理的本质就是权限分离+访问控制:root作为超级管理员管系统,普通用户各司其职,只拿自己该拿的权限,只从允许的机器登录。
回头想想,你从装完MySQL就一直用root,是不是相当于拿着金库钥匙去买早饭?既没必要又危险。从今天起,先执行select User,Host from mysql.user;查一下自己的账号列表,把高危的%账号整改掉,给自己的业务账号单独建个用户,分配对应库的权限------安全这根弦,从初学就绷紧。