第 09 章只读模式

只读模式是「按连接」的一个开关。打开以后,这个连接上的所有写操作都被禁用, 编辑能力整个关掉。它用来解决一个具体的问题:别手滑改坏生产库

为什么需要它

TablePlus 那类工具有一个更重的保护机制:每次写操作都要求重新输入数据库密码。 那个方案确实有效,但每次改个数据都要输密码,用起来很烦。

TableLite 用一个更轻的替代:把生产连接的编辑能力整个关掉。 想看数据就看,想跑 SELECT 就跑,但改不了。 真要改的时候,去连接菜单里把开关关掉——这一步足够让你意识到自己在做什么。

它不是权限控制

只读模式只做语句级别的拦截,是给「不会故意搞破坏的自己」用的护栏, 不是安全边界。真正的安全边界应该由数据库账号权限保证—— 给这个连接配一个只有 SELECT 权限的账号,那才是拦得住人的做法。

在哪里开关

位置操作
连接配置表单 → 基本信息勾上「只读」
打开连接后菜单「连接 → 只读模式」,随时可以切换,不用重连

这个状态保存在连接配置里,下次打开这个连接仍然生效。

只读的视觉标识

只读连接在界面上有五处标识,随便瞟一眼都能看出来。这是刻意的重复—— 防的就是「我以为自己在测试库上」。

只读模式的视觉标识 ① 连接列表 🔒 生产 app@10.0.2.5:3306/app_prod · 只读 ② 连接切换器 🔒 生产 ③ 工具栏颜色带 用连接配置里选的颜色着色,生产库建议设红色 ④ 窗口标题栏 生产(只读)— app_prod ⑤ 状态栏 生产 · app_prod · MySQL 8.0.36 · utf8mb4 · 只读 ← 用醒目颜色标出来 进入只读连接时会短暂显示一条状态栏提示: 该连接处于只读模式,所有写操作已被禁用。 工具栏的变更操作组整体禁用,悬停时说明原因: 放弃 预览 提交修改 ↑ 悬停禁用按钮时的提示:该连接处于只读模式,无法提交修改 SQL 编辑器工具栏在只读模式下常驻一行提示: 只读模式:仅允许 SELECT / SHOW / EXPLAIN / DESC
图 9-1 只读连接的五个标识位置,以及被禁用的变更操作组。
位置表现
连接列表名称前显示锁图标 🔒,摘要末尾追加 · 只读
连接切换器名称前显示锁图标 🔒
工具栏颜色带用连接颜色着色(生产建议设红色)
状态栏连接信息末尾追加 · 只读,用醒目颜色
标题栏显示 连接名(只读)

被禁止的操作

表数据视图

对象树

导入

表结构视图

不受影响——它本来就是只读的。

SQL 编辑器里的拦截

执行前会检查每条语句的类型,只允许这四类:

允许说明
SELECT
SHOW
EXPLAIN / DESCRIBE / DESC
WITH 开头的查询前提是最终是查询而不是写操作
拒绝说明
INSERT / UPDATE / DELETE / REPLACE
CREATE / ALTER / DROP / TRUNCATE / RENAME
GRANT / REVOKE
LOAD DATA会往表里灌数据
CALL存储过程内部可能写数据,无法预知,所以一律拒绝
SET可能改变会话状态,影响后续语句的语义
LOCK / UNLOCK
只读模式拦截提示 只读模式 语句 3 被拒绝执行: UPDATE users SET name = 'x' WHERE id = 1; 当前连接处于只读模式,只能执行查询语句。 如需修改,请在连接菜单中关闭只读模式。 关闭
图 9-2 只读拦截提示。脚本里被挡下的语句会有一个标红的「只读拦截」结果标签。

混合脚本怎么处理

关闭只读模式

菜单「连接 → 只读模式」取消勾选。取消后立即生效,不需要重连。 但因为这是「解除保护」的动作,会给一次轻确认,防止手滑:

关闭只读模式确认 确定要关闭「生产」的只读模式吗? 关闭后可以修改数据、执行写操作。 这个连接指向的是生产数据库。 取消 关闭只读
图 9-3 关闭只读模式的确认弹窗。

提示文案汇总

场景文案
进入只读连接该连接处于只读模式,所有写操作已被禁用。
悬停被禁用的提交按钮该连接处于只读模式,无法提交修改
SQL 编辑器工具栏常驻只读模式:仅允许 SELECT / SHOW / EXPLAIN / DESC
语句被拦下当前连接处于只读模式,只能执行查询语句。如需修改,请在连接菜单中关闭只读模式。
表数据视图不可编辑的原因状态栏显示 该连接处于只读模式,同时字段栏顶部也写明这一句

已知限制

两道没拦住的口子
  • 存储过程 / 函数内部的行为无法拦截。 一个 SELECT my_func() 里如果偷偷写了数据,只读模式看不出来。 这就是为什么 CALL 会被一律拒绝——能拦的只有语句本身。
  • 它不是权限控制。 真要防住误操作甚至是误用,去数据库上给这个连接配一个只有只读权限的账号。 两个一起用最稳:账号层面拦得住,界面层面拦得早。