MySQL 5.7.20 - SELECT FOUND_ROWS()返回错误的结果

时间:2018-02-18 10:09:11

标签: mysql jdbc

使用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()分配不同的连接有关,但是查看代码根据调用线程分配相同的连接,所以我有这种可能性打折扣。

可以提供任何帮助。

1 个答案:

答案 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之前有人可以扫入并运行另一个查询。

此处的一个可能解决方法是在单个事务中运行两个查询,LIMITFOUND_ROWS查询。这将保证两个查询都以原子方式执行。