mysql主从复制账号必须授予replication slave权限,仅select或replication client不足;该账号专供从库io线程使用,权限粒度窄且不可省略。

MySQL主从复制账号必须用REPLICATION SLAVE权限
只给SELECT或REPLICATION CLIENT不够,从库IO线程连不上主库就会报错ERROR 1236 (HY000): Could not open log file或者Access denied; you need (at least one of) the SUPER or REPLICATION SLAVE privilege(s)。这个账号不是给人用的,是给从库内部线程用的,权限粒度很窄,不能省。
实操建议:
- 在主库上执行:
CREATE USER 'repl'@'%' IDENTIFIED BY 'strong_pass_2024';<br>GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';<br>FLUSH PRIVILEGES;
-
'repl'@'%'里的%要和从库实际连接IP匹配,内网环境建议写成'repl'@'192.168.1.%'更安全 - 密码不能含@、/等特殊字符,否则
CHANGE MASTER TO语句容易因解析出错失败
读写分离不等于自动分发SQL,应用层必须区分SELECT和INSERT/UPDATE/DELETE
MySQL本身没有内置读写分离路由逻辑。所谓“读写分离”,本质是让应用把SELECT发给从库,其余写操作发给主库。如果应用没做判断,全打到一个实例,权限再细也没用。
常见错误现象:
- 用
mysqli或PDO直连,硬编码写死一个host,根本没切库逻辑 - ORM(如Laravel Eloquent)配置了
read/write连接,但模型里用了DB::select()绕过读连接池,查的还是主库 - 事务中混用
SELECT和UPDATE,结果SELECT被发到从库,触发Statement violates GTID consistency错误
关键点:事务内所有语句必须走同一节点,哪怕只是SELECT也要走主库。
SHOW SLAVE STATUS里Seconds_Behind_Master为NULL或0不代表数据实时
这个值只反映IO线程和SQL线程的延迟,不包含网络传输、binlog写盘、从库磁盘I/O等真实耗时。尤其在大事务、高并发写入后,从库可能已追平,但最新几条记录还没刷到表里——因为InnoDB的redo log和buffer pool刷新有延迟。
实操建议:
- 不要依赖
Seconds_Behind_Master == 0就认为能读最新数据,业务强一致性场景该走主库还得走主库 - 监控得加一层:用
SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(@@timestamp)在从库执行,对比主库时间戳差值,比看Seconds_Behind_Master更准 - 从库开启
read_only=ON,但注意它不阻止super用户写入,所以复制账号绝不能有SUPER权限
复制账号密码改了,从库不会自动重连,必须手动STOP SLAVE; START SLAVE;
主库改了repl账号密码,从库的MASTER_PASSWORD还缓存在内存里,SHOW SLAVE STATUS里Slave_IO_Running: Yes可能维持很久,直到下次重连失败才暴露问题。这时候Seconds_Behind_Master会突然跳涨,错误日志出现Access denied for user 'repl'@'x.x.x.x' (using password: YES)。
应对方式:
- 改密码后,立刻在每个从库执行:
STOP SLAVE;<br>CHANGE MASTER TO MASTER_PASSWORD='new_pass';<br>START SLAVE;
- 别用
SET PASSWORD FOR 'repl'@'%',要用ALTER USER,否则旧版本MySQL可能不刷新权限缓存 - Ansible或脚本批量操作时,
CHANGE MASTER TO语句里MASTER_USER和MASTER_PASSWORD必须显式写出,不能省略
复制链路的脆弱性不在SQL语法,而在这些看似边缘的权限、状态、时序细节上。漏掉任意一环,读写分离就变成“读写都写主库”或者“从库查不到刚写的数”。











