使用Spring JdbcTemplate查询JDBC时,MySQL 5.7.20遇到了一个奇怪的问题。问题是SELECT FOUND_ROWS()并不总是返回正确的结果,有时似乎返回先前版本的查询执行的结果。例如:
Query 1 - FOUND_ROWS = 0 - LIMIT query = 0
Query 2 - FOUND_ROWS = 0 - LIMIT query = 2
Query 3 - FOUND_ROWS = 2 - LIMIT query = 2
Query 4 - FOUND_ROWS = 2 - LIMIT query = 0
以下是查询:
SELECT SQL_CALC_FOUND_ROWS questions.id, questions.question,
MATCH(questions.question) AGAINST('echo') as tscore,
MATCH(answers.answer) AGAINST('echo') as ascore,
MATCH(votes.comment) AGAINST('echo') as cscore
FROM questions
LEFT JOIN answers ON questions.id = answers.questionId
LEFT JOIN votes ON answers.id = votes.answerId
LEFT JOIN users ON questions.userId = users.id
WHERE
MATCH(questions.question) AGAINST('echo')
OR MATCH(answers.answer) AGAINST('echo')
OR MATCH(votes.comment) AGAINST('echo')
GROUP BY questions.question
ORDER BY (tscore + ascore + cscore) DESC
LIMIT 0,5;
紧接着致电:
SELECT FOUND_ROWS();
我最初认为这可能与JdbcTemplate连接池和为调用SELECT FOUND_ROWS()分配不同的连接有关,但是查看代码根据调用线程分配相同的连接,所以我有这种可能性打折扣。
可以提供任何帮助。
答案 0 :(得分:0)
我认为你可能对SQL_CALC_FOUND_ROWS
的功能有误解。来自MySQL documentation:
SELECT SQL_CALC_FOUND_ROWS *
FROM tbl_name
WHERE id > 100
LIMIT 10;
SELECT FOUND_ROWS();
使用FOUND_ROWS()
的第二个查询会返回 在未使用LIMIT
时返回的记录数。
所以这是对结果的正确解释:
Query 1 - returns 0 - would have returned 0 without LIMIT
Query 2 - returns 0 - would have returned 2 without LIMIT
Query 3 - returns 2 - would have returned 2 without LIMIT
Query 4 - returns 2 - would have returned 0 without LIMIT **
**最后的结果似乎很可疑,因为删除LIMIT
不应减少结果集的大小。
修改强>
如果查询4结果实际上是真实的,那么该查询的FOUND_ROWS
结果可能确实对应于另一个查询。你忽略了连接可能成为问题的可能性,但实际上你可能已经做得太快了。最有可能的是,您的Spring应用程序配置为维护连接池,即与数据库的一些固定数量的连接。但问题是,任何线程都可能使用它们,因此无法保证在您更改调用FOUND_ROWS
之前有人可以扫入并运行另一个查询。
此处的一个可能解决方法是在单个事务中运行两个查询,LIMIT
和FOUND_ROWS
查询。这将保证两个查询都以原子方式执行。