Pergunta

Eu tenho uma grande lista de URLs em uma tabela MySQL Innodb e os processos de trabalhadores que consultam o MySQL para um conjunto de URLs processar. Os URLs devem ser marcados imediatamente como processados, para que outros processos do trabalhador não desperdiçam recursos começando a processar os mesmos.

Atualmente, faço isso pela primeira vez para obter alguns URLs:

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

Então, no código, eu ingenuamente percorriam cada um desses URLs para marcá -lo como processado:

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

Estou perfeitamente ciente de como isso é bobo e ineficiente. Mais importante ainda, não há garantia de que outro processo de trabalhador não tentasse obter uma lista no meio das minhas atualizações. Qual é a bela maneira de fazer isso? Devo fazer uma transação, como?

Foi útil?

Solução

O seguinte aparece (por uma rápida olhada no manual MySQL 5) para estar disponível no MySQL; Não tenho certeza se é a melhor abordagem, mas é uma que já usei antes no 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;

Na verdade, no PostgreSQL, eu usaria um solteiro Atualizar a instrução com a cláusula de retorno de atualização, substituindo o seleto, mas essa é uma extensão específica do PostGresql.

Um problema em potencial que vejo com sua abordagem são URLs duplicados: se URL http://www.example.com/ Aparece duas vezes na sua tabela, digamos com os IDs 23 e 42, ele será devolvido com um desses dois IDs pela seleção, mas a atualização afetará as duas linhas. Não sei se esse comportamento faz sentido em seu aplicativo; Eu provavelmente colocaria algum tipo de restrição única nos URLs para que não pudesse acontecer e depois usar uma lista de IDs, não URLs, no IN Cláusula (que deveria ser mais rápida).

Outras dicas

Talvez você deva apenas selecionar todos os URLs primeiro e depois usar threads para analisá -los de forma assíncrona?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top