mysql只读用户必须显式撤销写权限再授予select权限,需严格匹配user@host(如'ro_user'@'127.0.0.1')、检查残留权限、逐库授权、注意information_schema细粒度限制,并执行flush privileges生效。

phpEnv 是 Windows 下的本地开发环境套件,它默认集成 MySQL(通常是 5.7 或 8.0),但不提供图形化权限管理界面。设置只读用户必须通过 MySQL 命令行手动操作,且容易因忽略主机名匹配、残留权限或未刷新导致“看似设了却仍能写”的问题。
CREATE USER 时必须指定 @'host',不能只写用户名
phpEnv 的 MySQL 默认绑定 127.0.0.1 和 localhost,但这两个在 MySQL 权限系统中是**不同 host**:前者走 TCP/IP,后者走 socket。PHP 应用若用 host=127.0.0.1 连接,而你只建了 'ro_user'@'localhost',就会连不上。
- 推荐统一用
'ro_user'@'127.0.0.1'(适配大多数 phpEnv 的 PDO/MySQLi 连接方式) - 如果应用明确用
localhost,则建'ro_user'@'localhost';不要混用或留空 - 避免用
'ro_user'@'%',phpEnv 是本机环境,无必要开放远程
GRANT SELECT 后必须显式 REVOKE 写权限
仅执行 GRANT SELECT ON mydb.* TO 'ro_user'@'127.0.0.1' 不够——MySQL 权限是叠加的,用户可能继承自旧账号、mysql.user 表残留或全局 USAGE 外的隐式权限。
- 先查当前权限:
SHOW GRANTS FOR 'ro_user'@'127.0.0.1'; - 彻底清空写能力:
REVOKE INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, TRIGGER ON *.* FROM 'ro_user'@'127.0.0.1'; - 再授只读:
GRANT SELECT ON `mydb`.* TO 'ro_user'@'127.0.0.1';(注意库名用反引号,防短横线或关键字报错) - 别漏掉
FLUSH PRIVILEGES;,否则新权限不生效
PHP 连接后写操作报错但 SELECT 正常,说明权限已生效
用 PDO 测试时,常见误判点是没等连接真正建立就断言失败。正确验证顺序:
- 新开命令行,用该用户直连:
mysql -u ro_user -p -h 127.0.0.1 -D mydb - 执行
SELECT COUNT(*) FROM users;→ 应返回数字 - 执行
INSERT INTO users(name) VALUES('test');→ 必须报ERROR 1142 (42000): INSERT command denied - 执行
SHOW GRANTS FOR CURRENT_USER;→ 输出里只应有SELECT,无其他 DML/DCL 权限行
phpEnv 中的 MySQL 8.0+ 需额外注意 information_schema 访问限制
某些 PHP ORM(如 Laravel 的 Schema 检查)或监控脚本会执行 SHOW CREATE TABLE 或 SELECT * FROM information_schema.COLUMNS。MySQL 8.0 默认禁止普通用户查 information_schema,即使有目标库的 SELECT 权限。
- 如需支持结构查询,加一条:
GRANT SELECT ON `information_schema`.`COLUMNS` TO 'ro_user'@'127.0.0.1'; - 但不要开放整个
information_schema,尤其禁用SCHEMATA和TABLES(会暴露所有库名) - 不建议开
PROCESS或SHOW VIEW,它们不属于只读范畴,且 phpEnv 开发场景通常不需要
最容易被跳过的其实是 host 匹配和 FLUSH PRIVILEGES —— 很多人在 phpEnv 的 MySQL 控制台里敲完 GRANT 就以为完了,结果 PHP 连的是另一个 host 上下文,或者权限缓存没刷,写操作照常成功。务必用全新终端、全新连接验证,而不是复用已有会话。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











