如何防止在竞争条件下选择found_rows?

时间:2017-10-25 12:58:16

标签: mysql transactions

我必须运行具有限制和偏移量的查询,并且还需要构建分页的结果总数。这是一个复杂的查询,有很多条件和连接,所以我想避免两次查询只是为了计算。

根据mysql docs,我可以这样做:

mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
    -> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();

但是当我一次收到数千个请求时会发生什么,最终会出现这种情况:

mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
    -> WHERE __CONDITION1__ > 100 LIMIT 10; //count from query 1
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
    -> WHERE __CONDITION2__ LIMIT 10; //count from query 2
mysql> SELECT FOUND_ROWS(); //should be count form query 1 but it's count from query 2
mysql> SELECT FOUND_ROWS(); // count from query 2 but it's always 1

我已将查询封装在单独的交易中,但据我了解there's no guarantee it'll prevent this race condition.

所以有两个问题,我可以某种方式强制我的交易来阻止这种竞争条件吗? 如果没有,是否有另一种方法可以不再执行查询并检索计数?

1 个答案:

答案 0 :(得分:1)

在交易方面存在某些问题,不同的隔离级别会阻止更多或更少的交易。我在答案here中对此进行了描述 像幻像读取这样的问题会影响像你这样做的选择的结果,是的。但是SQL_CALC_FOUND_ROWS的结果会在查询完成后立即存储,并在您在同一会话中执行另一个查询时立即丢失。这是重要的部分。 SQL_CALC_FOUND_ROWS是会话绑定。没有办法,另一个会话中的另一个查询的结果存储在当前会话中。 SQL_CALC_FOUND_ROWS的使用不受竞争条件的限制。 SELECT查询的结果,是,但不是FOUND_ROWS()的结果。不要混淆这个。