2009-03-20 2 views
0

MySQL InnoDB 테이블에 엄청난 URL 목록이 있고 처리 할 URL 집합을 MySQL에 쿼리하는 작업자 프로세스가 있습니다. URL은 처리중인 것으로 즉시 표시되어야하므로 다른 작업자 프로세스가 동일한 작업 프로세스를 시작함으로써 리소스를 낭비하지 않습니다.MySQL을 사용하여 작업자 프로세스에 작업을 할당하는 올바른 방법

현재 내가 먼저 일부 URL을 얻기 위해이 작업을 수행 :

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

다음 코드에서 나는 그 각 URL을 통해 순진 루프를 표시하는 처리되는 같이

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

난 완벽 해요 이것이 얼마나 어리 석고 비능률적인지를 깨닫는다. 더 중요한 것은 다른 작업자 프로세스가 업데이트 중에 목록을 가져 오지 않을 것이라는 보장이 없습니다. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 어떻게해야 거래를 할 수 있을까요?

답변

2

MySQL에서 사용할 수 있도록 다음 내용이 나타납니다 (MySQL 5 설명서를 한눈에 볼 수 있음).

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; 

사실 PostgreSQL을에 나는의 자리를 복용 UPDATE의 복귀 절과 함께 단일 UPDATE 문을 사용합니다 : 나는 그것이 최선의 방법입니다,하지만 난 PostgreSQL을에 이전에 사용했던 하나입니다 있는지 확실하지 않습니다 SELECT하지만 PostgreSQL 관련 확장입니다.

접근법에서 볼 수있는 잠재적 인 문제 중 하나는 중복 된 URL입니다. http://www.example.com/ URL에 테이블에 ID 23과 42가 두 번 나타나면 SELECT를 통해 두 ID 중 하나가 반환되지만 업데이트가 영향을받습니다 두 행. 그 행동이 당신의 어플리케이션에서 의미가 있는지 나는 모른다. URL에 일종의 UNIQUE 제약 조건을 넣을 수 있으므로 IN 절 (더 빨리 수행해야 함)에서 URL이 아닌 ID 목록을 사용하십시오.

+0

감사합니다. 그러나 쉼표로 구분 된 [URL 목록]을 먼저 코드에 만들 필요없이 순수한 SQL 방식으로 생각할 수 있습니까? – Bemmu

+0

글쎄, 당신은 항상 그 비트를 하위 쿼리 (SELECT 문을 복사하여 붙여 넣기)로 대체 할 수 있습니다. 그 코드가 실제로 얼마나 잘 수행 될지 모르겠다. 실제로 코드 버전보다 낫다. – kquinn

0

어쩌면 모든 URL을 먼저 선택한 다음 스레드를 사용하여 비동기 적으로 구문 분석해야할까요?

+0

실제로 여러 컴퓨터가 URL을 처리하고 있으며 HTTP 요청을 사용하여 목록을 전달합니다. – Bemmu

관련 문제