2017-10-25 8 views
1

私は、制限とオフセットを持つクエリを実行する必要がありますまた、ページングを構築する結果の合計数が必要です。多くの条件と結合を持つ複雑なクエリですので、カウントを取得するために2回だけクエリを実行しないようにしたいと考えています。レースコンディションでselect found_rowsが壊れるのを防ぐには?

mysql docsによると、私はこれを行うことができます。

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 
を:私は一度のリクエストの数千を取得していたときに

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

をしかし、何が起こる、最終的にこの問題が発生したインスタンスが存在します

私はクエリを別々のトランザクションでカプセル化しましたが、私が理解する限りですthere's no guarantee it'll prevent this race condition.

したがって、私は何とかこの競合状態を防ぐために私の取引を強制することができますか? そうでない場合は、もう一度クエリを実行してカウントを取得しないでもう一度やり直す方法がありますか?

答えて

0

トランザクションに関しては、いくつかの問題があり、異なる分離レベルは多少の問題を防ぎます。私は私の答えでこれを記述したhere
たとえば、ファントムの読み込みのような問題は、そのような選択の結果に影響する可能性があります。しかし、SQL_CALC_FOUND_ROWSの結果は、クエリが終了するとすぐに格納され、同じセッションで別のクエリを実行するとすぐに失われます。それは重要な部分です。 SQL_CALC_FOUND_ROWSはセッションバインドです。別のセッションの別のクエリの結果が現在のセッションに保存されるという方法はありません。 SQL_CALC_FOUND_ROWSの使用は競合条件の対象ではありません。 SELECTクエリの結果、FOUND_ROWS()の結果ではありません。これを混同しないでください。

関連する問題