Frage

Ich habe eine riesige Liste von URLs in einer MySQL InnoDB -Tabelle und Arbeitsprozesse, die MySQL für eine Reihe von URLs abfragen. Die URLs sollten sofort als verarbeitet markiert werden, sodass andere Arbeitsprozesse keine Ressourcen verschwenden, indem sie dieselben verarbeiten.

Derzeit mache ich das zuerst, um einige URLs zu erhalten:

SELECT DISTINCT url FROM urls WHERE task_assigned is NULL ORDER BY id LIMIT 100

Dann schaue ich in Code naiv durch jede dieser URLs, um sie als verarbeitet zu markieren:

UPDATE urls SET task_assigned = NOW() WHERE url = ? COLLATE utf8_bin

Ich bin mir vollkommen bewusst, wie albern und ineffizient das ist. Noch wichtiger ist, dass es keine Garantie dafür gibt, dass ein anderer Arbeitsprozess nicht versucht, eine Liste in der Mitte meiner Updates zu erhalten. Was ist der schöne Weg, dies zu tun? Soll ich es zu einer Transaktion machen, wie?

War es hilfreich?

Lösung

Das Folgende erscheint (um einen kurzen Blick auf das MySQL 5 -Handbuch), um in MySQL verfügbar zu sein. Ich bin mir nicht sicher, ob es der beste Ansatz ist, aber ich habe es zuvor in PostgreSQL verwendet:

BEGIN TRANSACTION;
SELECT DISTINCT url FROM urls WHERE task_assigned is NULL ORDER BY id LIMIT 100 FOR UPDATE;
UPDATE urls SET task_assigned = NOW() WHERE url IN [list of URLs] COLLATE utf8_bin;
COMMIT;

Eigentlich würde ich in PostgreSQL a verwenden Single Aktualisieren Sie die Anweisung mit der Rückgabeklausel des Updates, die den Platz der Auswahl übernehmen, aber das ist eine PostgreSQL-spezifische Erweiterung.

Ein potenzielles Problem, das ich mit Ihrem Ansatz sehe, ist doppelte URLs: Wenn URL http://www.example.com/ In Ihrer Tabelle erscheint zweimal in Ihrer Tabelle, beispielsweise mit den IDs 23 und 42, wird von dem SELECT mit einem dieser beiden IDs zurückgegeben, aber das Update wirkt sich auf beide Zeilen aus. Ich weiß nicht, ob dieses Verhalten in Ihrer Anwendung sinnvoll ist. Ich würde wahrscheinlich eine einzigartige Einschränkung für URLs setzen, damit es nicht passieren kann, und dann eine Liste von IDs, nicht von URLs, in der IN Klausel (die schneller sein sollte).

Andere Tipps

Vielleicht sollten Sie zuerst alle URLs auswählen und dann Threads asynchron analysieren?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top