我正在使用springboot应用程序并连接到Azure Mysql。 在应用程序内部的方法调用中,编写了有关spring方面的内容,该方面对Azure MySql db进行了调用。 以下是从方面和方法执行查询的顺序
@Autowired
EntityManager entityManager
insert into <table name > values ();
为了执行此查询,使用了以下代码 EntityManager newEntityManager = entityManager.getEntityManagerFactory().createEntityManager();
String nativeSql = "insert into table1 values('1','abc;)";
newEntityManager.getTransaction().begin();
try{
newEntityManager.createNativeQuery(nativeSQL).executeUpdate();
entityManager.getTransaction().commit();
} catch (RuntimeException e) {
newEntityManager.getTransaction().rollback();
}finally{
newEntityManager.close();
}
@Transactional(readOnly=true)
EntityManager newEntityManager = entityManager.getEntityManagerFactory().createEntityManager();
String nativeSql = "update table2 set status='dead' where name='abc'";
newEntityManager.getTransaction().begin();
try{
newEntityManager.createNativeQuery(nativeSQL).executeUpdate(); //error occurs at this line
entityManager.getTransaction().commit();
} catch (RuntimeException e) {
newEntityManager.getTransaction().rollback();
}finally{
newEntityManager.close();
}
以下是完全错误
2019-02-10 23:18:00.959错误[bootstrap,c577f32a3b673745,c577f32a3b673745,false] 10628 --- [nio-8106-exec-2] ohengine.jdbc.spi.SqlExceptionHelper:无法在只读事务。
但是,当应用程序与本地mysql(在我的情况下为MariaBb)连接时,相同的代码也可以正常工作。 即使与Azure MSSQL连接,此代码也可以正常工作。 但是与Azure MySQL连接时会发生错误。
答案 0 :(得分:0)
不确定这是正确的解决方案,但是我对MariaDB遇到同样的问题,这非常令人困惑。我尝试使用show variables WHERE Variable_name like 'tx_%'
跟踪事务的状态,但是即使我实际运行只读事务,它也始终将tx_read_only
显示为OFF
。因此,我不知道如何确定事务是否为只读。
但是我将我的问题确定为一个相当模糊的场景。在报告有问题的有问题的读写事务之前,我运行了另一个只读事务。两者都使用相同的物理事务,并且以某种方式泄漏了“只读性”。但是,当我在第一个RO事务中使用Connection.getMetaData()
然后使用metaData.getColumns(...)
时,它失败了。我们需要检查单个表的列。
当我将事务读取元数据切换为读写时,问题没有出现,但如果我们怀疑只读泄漏到另一个(逻辑)连接,这是有道理的。顺便说一句:我们在单个Hikari连接池上方使用了Hibernate和普通JDBC的组合,因此这可能是一个因素。
后来,我们更改了查找元数据的方式。我们准备了一个语句,其中SELECT
不返回任何内容,然后询问resultSet.getMetaData()
。这不仅对于单个表(特别是在Oracle上,使用Connection.getMetaData()
花费了大约5分钟的时间)要快得多,而且不是会导致问题,即使我阅读了只读事务中的元数据。
所以这很奇怪-问题发生在以下时间:
Connection.getMetaData()
读取元数据时(必须满足两个条件以确保失败)。我检查了在成功情况下使用只读事务从空的SELECT结果集中读取元数据时,是否确实使用了完全相同的JDBC连接。读写事务没有问题。我认为问题可能出在处理连接的元数据上,我在resultSet.close()
的结果集中添加了MetaData.getColumns()
,但这里没有帮助。最后,我完全避免了Connection.getMetaData()
。
因此,尽管我仍然不知道确切的问题出在哪里,但我可以解决它,并确保该连接似乎适用于下一个读写事务,表明没有丢失的清理/只读泄漏。 >
另一个特点是:我们使用SET TRANSACTION READ ONLY
语句启动MySQL和MariaDB的只读事务。它在两个数据库上应该以相同的方式工作。当我改用START TRANSACTION READ ONLY
时,它工作正常。即使当我使用“错误”的方式访问表元数据时。
但是,很抱歉,它并不表示OP在MySQL上为什么有问题。