MySQL无默认用户权限,仅初始化生成受限的root@localhost超级账户;所有新用户权限全为N,必须显式GRANT;直接修改权限表需FLUSH PRIVILEGES生效;权限是缓存+持久化双机制,绕过GRANT操作易致脱节。

mysql 没有“默认授予用户”的权限,只有初始化后自动生成的 root@localhost 账户——它拥有全部权限,但被严格限制在本地连接,且初始密码不为空(MySQL 5.7+)或为空(--initialize-insecure 启动时)。这不是“默认权限”,而是安装脚本预设的**唯一超级账户**;所有其他用户,包括你 CREATE 出来的,权限全为 N(拒绝),除非显式 GRANT。
初始化后 root 权限看似高,实则受限严重
安装完成后,mysqld --initialize 会写入一条 root@localhost 记录到 mysql.user 表,字段 authentication_string 已加密,account_locked 为 N,plugin 通常是 caching_sha2_password。但它不能远程登录、不能执行 SHOW DATABASES(除非先 USE mysql)、甚至可能连 information_schema 都受限——因为权限虽全,但 host 是 localhost,而 MySQL 的权限匹配是 Host + User 二元组精确比对。
- 用临时密码登录后立刻执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'StrongPass123!'; - 别急着开
'root'@'%':生产环境应删掉非本地 root 记录,或仅保留'root'@'10.10.20.%'这类内网段 -
SELECT user,host,authentication_string FROM mysql.user;可确认是否残留空密码或匿名用户(如''@'localhost')
新用户创建后权限为零,GRANT 不是可选项而是必做动作
执行 CREATE USER 'app'@'192.168.1.%' IDENTIFIED BY 'P@ss2026'; 后,该用户能连上,但执行任何 SQL 都报 ERROR 1044 (42000): Access denied for user...——因为 mysql.db、mysql.tables_priv 等表里全无对应行,所有权限位都是 N。MySQL 不会“默认给 SELECT”或“默认允许 USE 数据库”。
- 必须配对使用:
CREATE USER+GRANT,不能省略后者 - 若只授
GRANT SELECT ON mydb.*,用户仍无法USE mydb,需额外GRANT USAGE ON mydb.*或确保mydb在mysql.db中有匹配的Db+Host+User记录 -
GRANT ALL PRIVILEGES ON mydb.*≠ “只读+写”,它包含DROP、ALTER、CREATE VIEW等高危操作,生产环境慎用
FLUSH PRIVILEGES 大多时候是冗余操作,但某些场景下它真能救命
用 GRANT 授权后无需 FLUSH PRIVILEGES(MySQL 5.7+ 自动重载缓存),但以下情况必须加:
- 你手贱直接
UPDATE mysql.user SET authentication_string=...修改了密码字段(不该这么干,但有人试过) - 用
INSERT INTO mysql.db手动插入数据库级权限(同样不推荐,但旧脚本或迁移时偶发) - MySQL 8.0+ 动态权限(如
BACKUP_ADMIN)需FLUSH PRIVILEGES才生效,GRANT本身不触发刷新
错误现象:改完 mysql.user 密码字段却仍提示 Access denied,就是忘了刷缓存。
权限表损坏时,别修表,要重置或导入干净结构
如果误删 mysql.user 里的 root@localhost 行,或清空了 authentication_string,不要试图 INSERT 回去——plugin、password_last_changed、account_locked 字段必须协同更新,否则认证失败且无报错提示。
- 优先从同版本干净实例导出结构:
mysqldump --no-data --skip-triggers mysql > mysql_schema.sql,再导入修复 - MySQL 8.0+ 可运行:
mysqld --upgrade=FORCE --user=mysql --datadir=/var/lib/mysql,强制校验并重建系统表 - 极端情况(如整个
mysql库丢失):备份业务库后重装 MySQL,再用mysqldump --all-databases导入,别碰原始权限表文件
最常被忽略的一点:权限不是“配置一次就永久有效”,它是动态加载的缓存+持久化表双机制,任何绕过 GRANT 的直写操作,都会让两者脱节——看起来改了,其实没生效。










