Domanda

Ho un enorme elenco di URL in una tabella di MySQL InnoDB, e processi di lavoro che query MySQL per una serie di URL da elaborare. Gli URL devono immediatamente essere contrassegnati come in fase di elaborazione, in modo che altri processi di lavoro non sprecare risorse per iniziare a elaborare le stesse.

Al momento ho faccio per ottenere alcuni URL:

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

Poi nel codice ingenuamente ciclo attraverso ciascuna di tali URL per contrassegnare come in lavorazione:

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

Sono perfettamente consapevole di quanto stupida e inefficiente questo è. Ancora più importante v'è alcuna garanzia che un altro processo di lavoro non avrebbe cercato di ottenere un elenco nel mezzo dei miei aggiornamenti. Qual è il bel modo per fare questo? Devo fare una transazione, come?

È stato utile?

Soluzione

viene visualizzato il seguente (per una rapida occhiata al manuale di MySQL 5) per essere disponibile in MySQL; Io non sono sicuro se è l'approccio migliore, ma è quella che ho usato prima in PostgreSQL:

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;

In realtà nel PostgreSQL avrei usato un solo UPDATE con la clausola RETURNING di UPDATE prendere il posto del SELECT, ma che è un'estensione specifica-PostgreSQL.

Un potenziale problema che vedo con il tuo approccio è URL duplicati: se url http://www.example.com/ appare due volte nella tabella, dicono con ID 23 e 42, si otterrà tornato con uno di quei due ID dal SELEZIONA ma l'aggiornamento sarà colpire sia righe. Non so se tale comportamento ha un senso nella propria applicazione; Io probabilmente mettere un qualche tipo di vincolo UNIQUE sugli URL in modo che non potesse accadere, e quindi utilizzare un elenco di ID, e non gli URL, nella IN clausola (che dovrebbe essere più veloce).

Altri suggerimenti

Forse dovresti selezionare tutti gli URL prima e poi utilizzare i thread per analizzare loro in modo asincrono?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top