2017-10-25 3 views
1

Ich muss eine Abfrage ausführen, die ein Limit und einen Offset hat, und ich benötige auch die Gesamtzahl der Ergebnisse, um Paginierung zu erstellen. Es ist eine komplexe Abfrage mit vielen Bedingungen und Joins, daher möchte ich vermeiden, dass die Abfrage zweimal ausgeführt wird, nur um eine Zählung zu erhalten.Wie kann verhindert werden, dass found_rows bei Rennbedingungen beschädigt wird?

Nach mysql docs kann ich dies tun:

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

Aber was passiert, wenn ich Tausende von Anfragen zu einem Zeitpunkt bekommen, schließlich wird es eine Instanz geben, wo dies der Fall ist:

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 

Ich habe die Abfragen in separaten Transaktionen gekapselt, aber soweit ich weiß there's no guarantee it'll prevent this race condition.

So gibt es zwei Fragen, Kann ich meine Transaktion irgendwie erzwingen, um diesen Wettlauf zu verhindern? Wenn nicht, gibt es eine andere Möglichkeit, dies zu tun, ohne die Abfrage erneut auszuführen und eine Zählung abzurufen?

Antwort

0

Es gibt bestimmte Probleme bei Transaktionen und unterschiedliche Isolationsstufen verhindern mehr oder weniger davon. Ich habe das in meiner Antwort here beschrieben.
Ein Problem wie das Phantom lesen zum Beispiel, kann das Ergebnis einer Auswahl beeinflussen, wie Sie es tun, ja. Das Ergebnis von SQL_CALC_FOUND_ROWS wird jedoch gespeichert, sobald die Abfrage abgeschlossen ist und verloren ist, sobald Sie eine andere Abfrage in derselben Sitzung ausführen. Das ist der wichtige Teil. SQL_CALC_FOUND_ROWS ist Sitzung gebunden. Es gibt keine Möglichkeit, dass das Ergebnis einer anderen Abfrage in einer anderen Sitzung in Ihrer aktuellen Sitzung gespeichert wird. Die Verwendung von SQL_CALC_FOUND_ROWS unterliegt nicht den Rennbedingungen. Das Ergebnis der SELECT-Abfrage, ja, aber nicht das Ergebnis von FOUND_ROWS(). Verwechsle das nicht.

Verwandte Themen