Navicat的“只读连接”仅为界面提示,实际权限由数据库账号的GRANT/REVOKE决定;必须通过SQL精确配置user@host、ON db.table及显式撤销INSERT/UPDATE/DELETE等写权限,并验证生效。

Navicat 本身不控制数据库读写权限,“只读连接”只是界面提示,真正起作用的是数据库账号的 GRANT 和 REVOKE 配置。团队成员能执行 DELETE 或 DROP,不是 Navicat 没锁住,而是他们连进去用的那个数据库用户本身就拥有这些权限。
Navicat 的“只读连接”设置根本不管用
在 Navicat 连接属性里勾选 “Read Only” 或把成员设为 Cloud 的 Viewer 角色,只会让界面禁用部分按钮(比如新建表、导出模型),但完全不限制 SQL 执行。用户仍可双击打开查询窗口,手写 UPDATE users SET status=0 并成功运行——只要数据库账号有对应权限。
常见错误现象:
- 以为勾了“只读”就安全,结果测试人员误删了测试库数据
- Cloud 后台设了 Viewer,但成员用公司笔记本从家里连,IP 不匹配
'dev_ro'@'10.20.30.45',直接连不上 - Navicat 新建用户向导里选了
mydb.*→ 实际开了整库 SELECT,包含敏感日志表
必须手动执行数据库级 GRANT/REVOKE
MySQL 表级只读账号不能靠 Navicat 图形向导生成,必须进查询窗口手写 SQL。关键点在于三要素精确匹配:user@host + ON db.table + 显式剔除写权限。
实操建议:
- 创建账号时明确指定 IP 段:
CREATE USER 'dev_ro'@'10.20.30.0/24' IDENTIFIED BY 'pwd123'; - 只授必要表:
GRANT SELECT ON myapp.users TO 'dev_ro'@'10.20.30.0/24'; - 显式拒绝所有写类操作:
REVOKE INSERT, UPDATE, DELETE, DROP, ALTER, CREATE ON myapp.* FROM 'dev_ro'@'10.20.30.0/24'; - MySQL 8.0.29 之前版本必须加:
FLUSH PRIVILEGES;
PostgreSQL 要额外补 schema USAGE 权限
MySQL 用户容易忽略 PostgreSQL 的两级权限模型:即使给了 SELECT ON TABLE,若没给上层权限,\dt 或 SHOW TABLES 会返回空,开发人员会误以为“连不上”或“没权限查”,其实是漏了 USAGE ON SCHEMA。
正确顺序是:
- 先授 database 连接权:
GRANT CONNECT ON DATABASE myapp TO dev_ro; - 再授 schema 使用权:
GRANT USAGE ON SCHEMA public TO dev_ro; - 最后授表查询权:
GRANT SELECT ON TABLE public.users TO dev_ro;
权限验证和上线前必查项
配置完别急着发给团队,先用该账号自己连一遍,跑几条典型语句验证边界:
- 执行
SELECT * FROM users LIMIT 1;→ 应成功 - 执行
INSERT INTO users (name) VALUES ('test');→ 应报错ERROR 1142 (42000): INSERT command denied - 执行
SHOW GRANTS FOR CURRENT_USER;→ 确认输出里没有INSERT、UPDATE等关键词 - 检查
mysql.user表(MySQL)或pg_roles(PG)确认 host 字段匹配实际来源 IP
最容易被忽略的是:UAT/生产环境的权限表是独立的,开发库配好的权限不会自动同步过去;云函数或手机热点导致 IP 不固定时,@'10.20.30.45' 会直接失效,得换代理或临时凭证方案。


















