应用账号必须用create user显式创建,不能靠grant隐式生成;mysql 8.0+已禁用该行为,否则报error 1410,且权限无法绑定、show grants查不到、drop user删不掉。

应用账号必须用 CREATE USER 显式创建,不能靠 GRANT 隐式生成
MySQL 8.0+ 已禁用 GRANT 隐式建户行为。直接写 GRANT SELECT ON app_db.* TO 'app'@'192.168.10.5' 会报错 ERROR 1410 (42000): You are not allowed to create a user with GRANT。
必须分两步:先 CREATE USER,再 GRANT。否则权限无法绑定到真实用户实体,后续 SHOW GRANTS 查不到,DROP USER 也删不掉。
- 显式建户时可一并设置安全策略:
PASSWORD EXPIRE INTERVAL 90 DAY、REQUIRE SSL、FAILED_LOGIN_ATTEMPTS 3 - 主机地址务必精确:用
'app'@'192.168.10.5',别用'app'@'%'—— 后者等于把门敞开 - 密码强度由插件控制:
validate_password_policy默认为STRONG,含大小写字母+数字+特殊字符+最小长度 12,测试环境临时调低需改全局变量
运维账号要分角色建,root 只用于紧急接管
运维不是一个人的事,得按职责切分账号:DBA 主账号、备份专用账号、监控只读账号、审计日志账号。每个账号的 host 和权限边界必须严格隔离。
比如监控账号只需查 performance_schema 和 information_schema,连业务库都不该碰;备份账号需要 LOCK TABLES 和 RELOAD,但绝不能有 DROP 或 GRANT OPTION。
-
DBA账号示例:CREATE USER 'dba_main'@'10.1.20.0/24' IDENTIFIED BY '...' WITH MAX_USER_CONNECTIONS 3; - 禁止给任何运维账号
ALL PRIVILEGES ON *.*—— 即便临时需要,也应通过SET ROLE动态激活,而非永久授予 - 所有运维账号启用
REQUIRE SUBJECT '/CN=dba-ops'(配合 TLS 客户端证书),比密码更可靠
权限必须落到具体库表,避免模糊匹配
GRANT SELECT ON *.* 或 GRANT ALL ON myapp.* 看似方便,实则埋雷。一旦新增系统库或中间件库(如 sys、mysql_innodb_cluster_metadata),这些账号就自动获得访问权。
真正安全的做法是白名单式授权:只列明业务实际用到的库和表,且优先用数据库级,慎用表级,列级权限仅用于脱敏场景。
- 应用账号典型授权:
GRANT SELECT, INSERT, UPDATE ON app_db.users TO 'app_rw'@'192.168.10.5'; - 运维备份账号需额外权限:
GRANT SELECT, LOCK TABLES, RELOAD ON app_db.* TO 'backup_user'@'10.1.20.10'; - 绝对不授
mysql库权限 —— 这里存着用户表、权限表,一旦被写,整个权限体系就崩了
权限生效不用死记 FLUSH PRIVILEGES
MySQL 8.0+ 的权限变更多数情况下自动生效,FLUSH PRIVILEGES 不是必需步骤。但它在两类场景下仍关键:
- 你手动修改了
mysql.user表(比如用UPDATE直接改authentication_string)—— 此时必须FLUSH,否则缓存不刷新 - 跨版本升级后首次授权 —— 某些旧插件缓存机制残留,
FLUSH是最稳妥的兜底操作
日常用 CREATE USER + GRANT 组合,权限立刻可用;但如果你看到权限没生效,先检查 host 是否拼错('app'@'localhost' ≠ 'app'@'127.0.0.1'),而不是条件反射敲 FLUSH PRIVILEGES。











