Pregunta

Tengo una enorme lista de direcciones URL en una tabla de MySQL InnoDB, y procesos de trabajo que consulta MySQL para un conjunto de direcciones URL para procesar. Las direcciones URL de inmediato deben marcarse como está siendo procesado, de manera que otros procesos de trabajo no desperdician recursos al comenzar a procesar los mismos.

Actualmente primera vez que hago esto para conseguir algunas de las URL:

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

Luego, en código ingenuamente bucle a través de cada una de las direcciones URL para marcarlo como siendo procesado:

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

Soy perfectamente consciente de lo tonta e ineficiente que es esto. Más importante aún no hay ninguna garantía de que otro proceso de trabajo no trataría de obtener una lista en la mitad de mis actualizaciones. ¿Cuál es la hermosa manera de hacer esto? ¿Debo hacerle una transacción, ¿cómo?

¿Fue útil?

Solución

aparece el siguiente (por un rápido vistazo a la manual de MySQL 5) para estar disponible en MySQL; No estoy seguro si es el mejor enfoque, pero es uno que he utilizado antes en 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;

En realidad, en PostgreSQL me gustaría utilizar un solo instrucción UPDATE con la cláusula de devolución de ACTUALIZACIÓN tomando el lugar de la instrucción SELECT, pero que es una extensión de PostgreSQL específica.

Un problema potencial que veo con su enfoque es URL duplicadas: si la URL http://www.example.com/ aparece dos veces en la tabla, dicen con ID 23 y 42, que conseguirá vuelto con una de esas dos identificaciones por el SELECT, pero la actualización afectar tanto a filas. No sé si ese comportamiento tiene sentido en su aplicación; Yo probablemente poner algún tipo de restricción única en las URL de modo que no podría suceder, y luego usar una lista de ID, no URLs, en el IN cláusula (que debería ser más rápido).

Otros consejos

Tal vez usted sólo debe seleccionar todas las direcciones URL, luego utilice hilos para analizarlos de forma asíncrona?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top