DBeaver本身不授予权限,只执行SQL或调用GRANT语句;真正生效的是数据库服务端权限系统。MySQL需手动指定库表并FLUSH PRIVILEGES,PostgreSQL须逐表授权,readonly=true仅为客户端约束,非真实权限控制。

直接给用户加 SELECT 权限不等于“只读”——DBeaver 本身不授予权限,它只是执行你写的 SQL 或调用图形界面背后的 GRANT 语句;真正生效的是数据库服务端的权限系统。如果你在 DBeaver 里点了几下就以为用户变只读了,很可能漏掉关键限制,比如没禁用 UPDATE、INSERT,也没关掉 DROP 或 CREATE,甚至用户还能删表。
MySQL 中用 DBeaver 执行 GRANT SELECT 时必须避开的坑
很多人在 DBeaver 的「用户」节点右键 → 「编辑用户」→ 「权限」页签里勾选 SELECT 就以为完事了,但实际权限可能没落到具体库或表上:
- 勾选的是全局权限(
GRANT SELECT ON *.*),但 MySQL 默认禁止非 super 用户跨库查information_schema或mysql系统库,结果连SHOW TABLES都报错 - 如果目标库是
reporting,但你在权限页签里没展开该 schema,只在顶层勾了SELECT,那语句生成的是GRANT SELECT ON *.*,不是GRANT SELECT ON reporting.* - DBeaver 自动生成的 SQL 可能不含
FLUSH PRIVILEGES,改完权限后连接不刷新,旧会话仍按老权限走
更稳妥的做法是:在 SQL 编辑器里手写并执行:
USE reporting; GRANT SELECT ON reporting.* TO 'report_reader'@'%'; FLUSH PRIVILEGES;
注意替换 reporting 和 report_reader 为你的实际库名和用户名。
PostgreSQL 用户只读必须逐表授权或用脚本批量处理
PostgreSQL 没有 GRANT SELECT ON database.* 这种语法,DBeaver 的图形化权限页签对 PG 基本无效——它只能设 role 层级属性(如 LOGIN、CREATEDB),不能自动遍历 public schema 下所有表授 SELECT。
正确做法是用 SQL 批量生成授权语句:
SELECT 'GRANT SELECT ON TABLE ' || tablename || ' TO readonly;' FROM pg_tables WHERE schemaname = 'public';
把结果复制执行,或者直接用 psql 执行:
psql -U admin -d mydb -c "SELECT 'GRANT SELECT ON TABLE ' || tablename || ' TO readonly;' FROM pg_tables WHERE schemaname = 'public';" | psql -U admin -d mydb
别忘了先建角色:CREATE ROLE readonly WITH LOGIN PASSWORD 'xxx';
DBeaver 连接参数里加 readonly=true 不是权限,是客户端约束
即使数据库用户真有写权限,你也可以在 DBeaver 的连接配置里加 JDBC 参数强制只读行为:
- 编辑连接 → 「驱动属性」→ 添加新属性:
readonly=true - MySQL 驱动会把这个转成
SET SESSION tx_read_only = 1(8.0+)或拦截写语句 - 这个设置只影响当前连接,不改变用户真实权限;适合临时调试或防止手滑
- 但它拦不住
DROP TABLE这类 DDL(除非数据库本身启用了read_only=ON)
所以它只是保险丝,不是保险箱。
验证只读是否真的生效,别只看 DBeaver 能不能点「编辑单元格」
DBeaver 界面里「结果集不可编辑」可能只是因为连接被设为只读模式,不代表用户没写权限。真正验证要看数据库反应:
- 用该用户连进命令行(
mysql -u report_reader -p),执行INSERT INTO t VALUES (1);,应报ERROR 1142 (42000): INSERT command denied - 执行
SHOW GRANTS FOR 'report_reader'@'%';,确认输出里只有SELECT,没有UPDATE、INSERT、DROP、ALTER - 检查是否误授了
USAGE+GRANT OPTION,这会让用户能给自己加权限
最常被忽略的一点:MySQL 的 read_only=ON 是实例级开关,对 super 用户无效,但能兜底防应用层误写;它和用户权限是两层机制,建议一起开。











