为什么启用服务器端预处理语句会导致CONCUR_UPDATABLE错误?

时间:2015-03-14 09:01:17

标签: mysql jdbc concurrency prepared-statement resultset

当我通过useServerPrepStmts jdbc标志启用服务器端准备好的状态时,结果集更新操作在第一次请求给定查询后

  

结果集不可更新。此结果集必须来自语句   使用ResultSet.CONCUR_UPDATABLE的结果集类型创建的,   查询必须只选择一个表,不能使用函数和必须   从该表中选择所有主键

当我禁用服务器端预处理语句时,结果集更新操作可以正常运行。

由于查询只涉及一个表,有一个主键,返回一行,并且不涉及任何函数,必须发生的是使用ResultSet.CONCUR_READ_ONLY创建预准备语句,然后缓存服务器端。对同一查询的后续请求将从缓存中提取准备好的语句,然后,即使客户端发送ResultSet.CONCUR_UPDATABLE rs.updateRow(),服务器上的并发仍设置为ResultSet.CONCUR_READ_ONLY

如果我在上面的假设中是正确的,那么在这种情况下如何覆盖服务器端缓存? (其他一切都没有准备好的语句缓存,只是结果集行操作受到影响)。

Linux(CentOS 5.7):

  

mysql-connector-java 5.1.33

     

mysql 5.6.20

修改

不相关我注意到第一个查询总是成功,在查询日志中有这个:SET SQL_SELECT_LIMIT=1,所有后续查询都失败了:SET SQL_SELECT_LIMIT=DEFAULT。不确定这是问题的原因,还是仅仅是副作用。猜猜我会尝试在客户端上手动setFetchSize,看看是否有所作为......

1 个答案:

答案 0 :(得分:0)

解决方法是在客户端上FOR UPDATE附加ResultSet.CONCUR_READ_ONLY select语句,并为新准备好的语句ResultSet.CONCUR_UPDATABLE并发。这允许服务器语句缓存,同时仍然能够修改JDBC ResultSet

旁注: select ... for update语句本身似乎没有资格进行缓存;即查询日志在每个请求上显示PrepareExecute行。