首页/数据/SQL 速查/只读事务的用途与写法
变更与事务52 条

只读事务的用途与写法

声明只读事务:给数据库优化空间、避免误写,适合报表、备份、批量导出连接。

SQL 速查数据更新于 2026-10-13

只读事务做什么

只读事务明确声明「这个事务不会写数据」:数据库可以省掉一部分锁与日志开销,同时任何写操作都会被直接拒绝,等于自带一道防误操作的保护。报表查询、备份、批量导出这类连接很适合用它。

基本信息

MySQL 语法START TRANSACTION READ ONLY
PostgreSQL 语法BEGIN READ ONLY 或 SET TRANSACTION READ ONLY
收益明确不写数据,系统可降低锁与日志开销
保护作用事务内写普通表会直接报错
例外PostgreSQL 的只读事务里仍可写临时表

典型使用场景

  • 报表与统计分析连接
  • 备份与批量导出
  • 只读从库上的应用连接
  • 给运维脚本加一层防手滑保护
  • 给 BI 工具配只读账号加只读事务的双重保护

MySQL 写法

MySQL 写法
START TRANSACTION READ ONLY;   -- 声明只读,写操作会直接报错

SELECT COUNT(*) FROM orders;
SELECT user_id, SUM(total) FROM orders GROUP BY user_id;

COMMIT;                        -- 跑完及时提交,别长期挂着

PostgreSQL 写法

PostgreSQL 写法
BEGIN READ ONLY;
-- 也可以写 SET TRANSACTION READ ONLY;
SELECT COUNT(*) FROM orders;
COMMIT;

-- 会话级设置:之后的事务默认只读
SET default_transaction_read_only = on;

两库对照

维度MySQLPostgreSQL
声明方式START TRANSACTION READ ONLYBEGIN READ ONLY 或 SET TRANSACTION
写普通表报错报错
写临时表受限允许
会话级默认有对应的事务特征设置default_transaction_read_only
主要收益降低锁与日志开销、防误写同上
只读事务不等于无锁:读取仍会产生一些锁开销,长时间运行的只读事务同样会阻碍系统清理,跑完要及时提交。
连接池里的连接会被复用:只读这类事务特征可能残留,用完要重置状态,避免影响同一个物理连接上的后续业务。
在只读从库上跑报表时,只读事务还能防住误写:配合只读账号,基本可以排除报表连接被当成写入数据源导致主从不一致的风险。
只读不等于一致性保证:需要可重复读的场景仍要显式设置隔离级别,只读事务只声明「不写」,并不改变快照与可见性规则。

易错点

  • 以为只读事务完全不产生锁开销:读取仍有少量锁,长只读事务同样会阻碍清理
  • 在只读事务里尝试写数据:会直接报错,多语句脚本混用读写时容易中断流程
  • 连接池复用残留事务特征:只读声明可能影响后续事务,用完要重置
  • 用只读事务替代权限控制:它能防误写但拦不住越权读,权限仍要单独配置
  • 在 PostgreSQL 里期待只读事务禁止写临时表:只读事务仍允许写临时表,别把它当安全边界

数据来源与参考

  • MySQL 8.0 Reference Manual · START TRANSACTION
  • PostgreSQL Documentation · SET TRANSACTION
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌