环境
系统平台:Linux x86-64 Red Hat Enterprise Linux 7
版本:4.5
症状
JavaSpring+Mybatis程序,Spring管理事务,运行报错:“不能在一个只读模式的事务中执行INSERT”。
org.springframework.jdbc.UncategorizedSQLException:
### Error updating database. Cause: com.highgo.util.PSQLException: 错误: 不能在一个只读模式的事务中执行INSERT
### The error may involve com.community.persistence.UserMapper.insertUser-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO cs_user (id, nick_name, login_name, login_pwd, email, phone, identity_card, createTime, updateTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
### Cause: com.highgo.util.PSQLException: 错误: 不能在一个只读模式的事务中执行INSERT ;
uncategorized SQLException for SQL []; SQL state [25006]; error code [0];
错误: 不能在一个只读模式的事务中执行INSERT;
nested exception is com.highgo.util.PSQLException: 错误: 不能在一个只读模式的事务中执行INSERT
问题原因
Spring的Read-only事务只会看到在这个事务开启时间点其他事务提交过的数据,并且不允许执行INSERT, UPDATE,DELETE语句,换句话说,在设置set transaction read only后,当前会话所见的数据图像,将不再受到其他会话事务的影响。所以瀚高、Oracle支持的只读事务不是为了优化性能,而是为了让这个事务中所有的查询操作看到的数据是一个时间点(开启事务)上的一致数据。MYSQL、SQL_SERVER根本没有只读事务的概念,之前使用MySQL时,该参数没有生效,所以未报错。
解决方案
将该事务修改为readOnly=false,如下: