하나의 스레드에 대해 하나의 테이블 행을 명시 적으로 선택하는 방법을 찾고 있습니다. 나는 크롤러를 작성했다.이 크롤러는 약 50 개의 병렬 프로세스로 작동한다. 모든 프로세스는 테이블에서 한 행을 가져 와서 처리해야합니다.높은 병렬 연결에서 하나의 테이블 행만 선택하십시오.
CREATE TABLE `crawler_queue` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`url` text NOT NULL,
`class_id` tinyint(3) unsigned NOT NULL,
`server_id` tinyint(3) unsigned NOT NULL,
`proc_id` mediumint(8) unsigned NOT NULL,
`prio` tinyint(3) unsigned NOT NULL,
`inserted` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `proc_id` (`proc_id`),
KEY `app_id` (`app_id`),
KEY `crawler` (`class_id`,`prio`,`proc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
지금 내 프로세스는 다음을 수행
이- 시작 DB 트랜잭션
- 이
SELECT * FROM crawler_queue WHERE class_id=2 AND prio=20 AND proc_id=0 ORDER BY id LIMIT 1 FOR UPDATE
- 같은 선택을 한 후 트랜잭션을 커밋
UPDATE crawler_queue SET server_id=1,proc_id=1376 WHERE id=23892
- 으로이 행을 갱신
이것은 다른 프로세스가 아직 처리 된 행을 가져올 수 없도록 도와줍니다.
mysqli::query(): (HY000/1205): Lock wait timeout exceeded; try restarting transaction (in /var/www/db.php l
ine 81)
mysqli::query(): (40001/1213): Deadlock found when trying to get lock; try restarting transaction (in /var/www/db.php line 81)
: 가끔 내 로그 (그래서 5 분마다 또는) 오류/경고의 두 가지 유형을 볼 수 있습니다 때문에이 선택 쇼
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE crawler_queue ref proc_id,crawler proc_id 3 const 617609 Using where
그러나 프로세스가 너무 높은 병렬 처리를 야기하는 것에 EXPLAIN 수행
내 질문은 : 누구나 올바른 방향으로 이러한 잠금 문제를 최소화 할 수 있습니까?
편집 2012년 12월 29일 (생산 상태로, 병렬 처리가 지금보다 3 ~ 4 배 높은 것, 그래서 더 많은 잠금 문제가있을 것이라고 가정) : 나는 인덱스 crawler
를 사용하는 SELECT
수정 힌트 : USE INDEX(crawler)
. 내 문제는 이제 lockwait 시간 초과입니다 (교착 상태가 사라짐).
편집 2012-12-31 : USE INDEX()
와 EXPLAIN
지금이다 (표는 이제 더 많은 데이터를 포함하고 있기 때문에 어떤 행 높다.가) : 나는 문제가 무엇을 말할 수에서
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE crawler_queue ref proc_id,crawler crawler 5 const,const,const 5472426 Using where
'LAST_INSERT_ID()'는'INSERT' 데이터 나'UPDATE'가 autoincrement 칼럼을 증가시킬 때만 값을 반환합니다 : ** EDIT ** http://stackoverflow.com/questions/ 1388025/how-to-get-id-of-the-last-updated-row-in-mysql 시도 – rabudde
테스트 한 결과 last_insert_id 값을 얻었으나 속임수가 듭니다. 하지만 그렇지 않았습니다.) 나는 그 질문에 설명 된 해결책이 갈 길이라고 믿습니다. 나는 나의 대답도 업데이트 할 것이다. – Xnoise