开发能删表是因为权限未按库限定或实例混用,如测试库与生产库共用实例、bind-address=0.0.0.0暴露端口、localhost连接绕过网络控制、主从配置不当致数据回流等。

MySQL用户权限只给SELECT,为什么开发还能删表?
权限配置不等于安全隔离。即使GRANT SELECT给了开发账号,只要该账号对数据库有DROP、ALTER或CREATE权限(哪怕来自USAGE以外的任意角色),就可能误操作或被利用。更常见的是:开发连的是测试库,但测试库本身和生产库共用同一MySQL实例,且mysql.user里没做库级限制。
- 检查真实权限用:
SHOW GRANTS FOR 'dev_user'@'%';,别只看GRANT语句,要看实际生效的权限集合 - 权限必须按库限定:
GRANT SELECT ON `test_db`.* TO 'dev_user'@'%';,不能写成ON *.* - 禁用
super_priv和drop_priv——哪怕只开一个DROP权限,也等于开了整库删除门 - 避免用
root账号做日常连接,哪怕加了IP白名单;用CREATE USER新建最小权限账号
MySQL配置文件里bind-address=0.0.0.0是不是很危险?
是,而且危险得非常隐蔽。这个配置让MySQL监听所有网卡,包括本机Docker桥接网卡、宿主机虚拟网卡、甚至云厂商内网网卡。开发环境容器如果没做网络策略,就可能从172.17.x.x段直接连上生产MySQL端口。
- 生产MySQL必须设为
bind-address = 127.0.0.1或具体内网IP(如10.10.20.5),绝不能留0.0.0.0 - 云环境还要在安全组/防火墙层面封掉3306端口对外暴露,仅允许运维跳板机或CI/CD服务IP访问
- 容器部署时,MySQL容器应使用
host network: false并显式指定--network=isolated-net,别用bridge默认网络 -
skip-networking=ON可彻底禁用TCP连接,只留socket通信,适合单机部署场景
mysqldump同步脚本里--host写localhost,为什么连上了生产库?
因为localhost在MySQL客户端里有特殊含义:它强制走Unix socket连接,绕过TCP/IP栈和所有网络层控制。如果生产MySQL也在本机跑(比如开发机装了MAMP/XAMPP),或者Docker Compose里MySQL服务名恰好叫mysql,而/etc/hosts又把localhost映射到了错误IP,结果就是dump脚本直连生产实例。
- 脚本中一律用具体IP或DNS名:
--host=10.10.20.5,而不是--host=localhost - 确认连接方式:
mysql -h localhost -u root -e "SELECT @@hostname;"和mysql -h 127.0.0.1 -u root -e "SELECT @@hostname;"返回可能不同 - 在
my.cnf客户端段加protocol=tcp,强制走TCP,避免socket歧义 - 自动化脚本开头加校验:
mysql -h $HOST -P $PORT -Nse "SELECT @@version_comment" | grep -q "production" && exit 1
MySQL主从复制怎么防止开发库反向写入生产主库?
主从不是单向保险丝。如果开发环境误配成从库却开了read_only=OFF,或用了log_slave_updates=ON再配上auto-increment-offset错配,就可能把开发数据“回流”进生产主库的binlog,触发级联同步。
- 所有从库必须设
read_only=ON,且生产主库额外加super_read_only=ON(MySQL 5.7+),防绕过 - 禁用
log_slave_updates在非中继场景——开发从库不需要再当主库发binlog - 检查
SHOW SLAVE STATUS\G里的Seconds_Behind_Master是否持续为0,异常延迟可能掩盖写冲突 - 用
replicate_ignore_db不如用replicate_wild_ignore_table精确,例如dev_%.比dev_test更防漏
真正难防的不是配置项,是人把prod和dev两个环境的my.cnf文件搞混后直接scp过去重启——这种事发生过不止一次。


















