从库查不到用户、报access denied是因为复制配置中replicate-ignore-db=mysql导致grant语句被跳过,所有权限变更未同步;需检查show slave status\g中的replicate_ignore_db字段,并避免直接操作mysql.user表,改用grant语句或重建权限结构。

为什么从库查不到用户、报Access denied,但主库一切正常
因为权限变更根本没进 binlog —— MySQL 8.0 默认虽开启 GRANT 日志记录,但前提是 log_bin=ON 且没配 replicate_ignore_db=mysql。只要从库的复制配置里有 mysql 在忽略列表中,所有 CREATE USER、GRANT 都会被跳过,SELECT user,host FROM mysql.user 在从库返回空就是最直接信号。
检查从库是否跳过了 mysql 库的复制
别只看主库配置,从库的 Replicate_Ignore_DB 才是真正生效的地方:
- 执行
SHOW SLAVE STATUS\G,重点看Replicate_Ignore_DB字段是否含mysql - 若用 GTID 模式,还要查
binlog_ignore_db(它影响主库写入,但同样会间接导致从库缺失事件) - 容器或 Ansible 批量部署时,
replicate_ignore_db=mysql常被模板默认注入,容易被忽略 - 临时验证:在主库执行
CREATE USER 'test'@'localhost'; GRANT SELECT ON *.* TO 'test'@'localhost';,再立刻在从库查SELECT User,Host FROM mysql.user WHERE User='test';—— 返回空就坐实问题
修复权限同步必须绕开 mysql.user 表直写
直接 INSERT INTO mysql.user 或 UPDATE mysql.user 是高危操作:
- 不会触发权限重载,
FLUSH PRIVILEGES也救不回来 - 生成的 binlog 事件格式异常,从库回放大概率中断(报错
HA_ERR_RBR_LOGGING_FAILED或直接SQL_THREAD停摆) - 正确路径只有两条:
GRANT语句(自动记 binlog + 自动重载),或全量重建权限表(见下一条) - 紧急情况下可在从库手动执行一次
FLUSH PRIVILEGES,仅用于确认内存权限是否加载——不是解决方案,只是诊断辅助
跨版本迁移后权限表结构不兼容怎么办
如果从 5.7 迁到 8.0 后账号全挂了,90% 是表结构错配,不是密码错了:
-
mysqldump --all-databases导出的旧mysql库含已废弃字段(如Password),而 8.0 要求authentication_string和password_last_changed等新字段 - 硬导入会报
ERROR 1067 (42000): Invalid default value for 'password_last_changed',甚至启动失败 - 安全做法是停库后执行:
mysqld --initialize-insecure --datadir=/var/lib/mysql --user=mysql,生成全新 8.0 权限表结构 - 再用
pt-show-grants或手动清理过的GRANTSQL 导入权限逻辑,而非原始数据行 - 注意插件兼容性:
caching_sha2_password客户端不支持时,得补一句ALTER USER 'xxx'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
最容易卡住的点不在语法对不对,而在从库的 Replicate_Ignore_DB 是否静默继承了错误配置;结构不兼容时,宁可重刷 mysql 库,也不要试图修补旧字段。











