bigywater.tech
Spring · 33

readOnly 的真实效果:MySQL 与 Hibernate flush 模式

@Transactional(readOnly = true) 只是个提示吗?MySQL 那边到底收到了什么?Hibernate 里改了实体会怎样?内层方法标 readOnly 有用吗?这篇在 Spring Framework 7.0.9、Hibernate 和 MySQL 26.7.0 上逐项验证。

6 条
readOnly = true 的方法在连接上留下的语句数(以 SET SESSION TRANSACTION READ ONLY 开始、READ WRITE 结束)
100 与 777
同样修改实体,readOnly = true 与 readOnly = false 事务结束后表里的 balance
321
外层读写事务里调用 readOnly = true 的内层方法后表里的 balance(内层写成功了)

JDBC 一侧

实测 · 本机执行输出
  readOnly = true 的方法执行时,那个连接上的语句:
    SET SESSION TRANSACTION READ ONLY
    SET autocommit=0
    select balance from acct where id = 1
    COMMIT
    SET autocommit=1
    SET SESSION TRANSACTION READ WRITE
  readOnly = true 里用 JdbcTemplate 写:失败 TransientDataAccessResourceException ← SQLException: Connection is read-only. Queries leading to data modification are not allowed.;表里 balance = 100
  readOnly = false(默认)里用 JdbcTemplate 写:成功;表里 balance = 500

readOnly 对应会话级的 READ ONLY / READ WRITE 切换,驱动在客户端拒绝写入。

Hibernate 一侧

实测 · 本机执行输出
  readOnly = true:修改受管实体 a.balance = 777,事务结束 → 表里 balance = 100(100 表示没有写进去)
    这次的 SQL 里有 UPDATE 吗?false
  readOnly = false:同样的修改 → 表里 balance = 777;SQL 里有 UPDATE 吗?true
  readOnly = true 里修改实体后手动 em.flush():成功;表里 balance = 100

只读事务里实体修改不会被刷新,手动 flush 也不报错。

加入外层事务

实测 · 本机执行输出
  外层读写事务里调用 readOnly = true 的内层方法(REQUIRED 加入外层事务):成功,返回 外层读写,里层 readOnly=true 的方法写成功了;表里 balance = 321;(内层方法是经过代理调用的,不是自调用)
  单独调用 readOnly = true 的 roFlag():readOnly=true

内层的 readOnly 对已有的读写事务无效。

分步演示

readOnly 的真实效果
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。用不带 Boot 的 Spring Framework 7.0.9 + JpaTransactionManager + Hibernate(Boot 4.0.8 的 BOM 带来的版本)+ HikariCP + 自己起的 MySQL 26.7.0 + mysql-connector-j 9.7.0;general_log 开在这个实例上(输出到表)
    • 没有验证:Hibernate 的读写分离或只读副本路由(见后面的 Data 篇);readOnly 对 JDBC 连接池只读连接的影响;MySQL 的 START TRANSACTION READ ONLY 与 SET SESSION 的区别;PostgreSQL 等其它数据库的 readOnly 行为;readOnly 事务的性能收益(没有测量)
    京ICP备2026067502号-1京公网安备11010502063487号