只读事务做什么
只读事务明确声明「这个事务不会写数据」:数据库可以省掉一部分锁与日志开销,同时任何写操作都会被直接拒绝,等于自带一道防误操作的保护。报表查询、备份、批量导出这类连接很适合用它。
基本信息
| 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;两库对照
| 维度 | MySQL | PostgreSQL |
|---|---|---|
| 声明方式 | START TRANSACTION READ ONLY | BEGIN READ ONLY 或 SET TRANSACTION |
| 写普通表 | 报错 | 报错 |
| 写临时表 | 受限 | 允许 |
| 会话级默认 | 有对应的事务特征设置 | default_transaction_read_only |
| 主要收益 | 降低锁与日志开销、防误写 | 同上 |
只读事务不等于无锁:读取仍会产生一些锁开销,长时间运行的只读事务同样会阻碍系统清理,跑完要及时提交。
连接池里的连接会被复用:只读这类事务特征可能残留,用完要重置状态,避免影响同一个物理连接上的后续业务。
在只读从库上跑报表时,只读事务还能防住误写:配合只读账号,基本可以排除报表连接被当成写入数据源导致主从不一致的风险。
只读不等于一致性保证:需要可重复读的场景仍要显式设置隔离级别,只读事务只声明「不写」,并不改变快照与可见性规则。