简体   繁体   English

如何防止select found_rows在竞争条件下中断?

[英]How to prevent select found_rows breaking on race conditions?

I have to run a query that has a limit and offset and I also need the total number of results to build pagination. 我必须运行一个具有限制和偏移量的查询,并且还需要总数的结果来建立分页。 It's a complex query with a lot of conditions and joins so I would like to avoid doing the query twice just to get a count. 这是一个具有很多条件和联接的复杂查询,因此我想避免为了获得计数而重复两次查询。

According to mysql docs I can do this: 根据mysql文档,我可以做到这一点:

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

But what happens when i'm getting thousands of requests at a time, eventually there will be an instance where this happens: 但是,当我一次收到数千个请求时会发生什么,最终将发生这种情况:

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

I've encapsulated the queries in separate transactions, but as far as I understand there's no guarantee it'll prevent this race condition. 我已经将查询封装在单独的事务中,但是据我所知,不能保证它会阻止这种竞争情况。

So there's two questions, can i somehow force my transaction to prevent this race condition? 所以有两个问题,我能以某种方式强迫我的交易来防止这种竞争状况吗? If not, is there another way of doing it without doing the query again and retrieving a count? 如果不是,是否还有另一种方法可以执行而无需再次执行查询并获取计数?

There are certain problems when it comes to transactions and different isolation levels prevent more or less of them. 涉及事务时存在某些问题,不同的隔离级别或多或少会阻止它们。 I've described this in my answer here . 我已经在这里的回答中对此进行了描述。
A problem like the phantom read for example, can affect the result of a select like you're doing it, yes. 例如,像幻像读取之类的问题可能会影响您所做选择的结果,是的。 But the result of SQL_CALC_FOUND_ROWS is stored as soon as the query finishes and is lost as soon as you execute another query in the same session. 但是,SQL_CALC_FOUND_ROWS的结果将在查询结束后立即存储,并在同一会话中执行另一个查询后立即丢失。 That is the important part. 那是重要的部分。 SQL_CALC_FOUND_ROWS is session bound . SQL_CALC_FOUND_ROWS已绑定会话 There is no way, that the result of another query in another session is stored in your current session. 无法将另一个会话中另一个查询的结果存储在当前会话中。 The use of SQL_CALC_FOUND_ROWS is not subject to race conditions. SQL_CALC_FOUND_ROWS的使用不受竞争条件的约束。 The result of the SELECT query, yes, but not the result of FOUND_ROWS(). 是SELECT查询的结果,但不是FOUND_ROWS()的结果。 Don't confuse this. 不要混淆这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM