MySQL 테이블을 동시에 읽고 쓸 수 있는 작업자가 여러 명 있다고 가정해 보겠습니다(예: jobs
). 각 작업자의 임무는 다음과 같습니다.
已排队
채용정보 찾기 RUNNING
작업자가 1단계를 실행할 때 적격한 작업(예: )이 없을 QUEUED
수도 있다는 점에 유의하세요.
지금까지 다음과 같은 의사 코드가 있습니다. 1단계에서 작업이 반환되지 않으면 거래를 취소(ROLLBACK
)해야 한다고 생각합니다. 아래 코드에서 이 작업을 어떻게 수행합니까?
BEGIN TRANSACTION; # Update the status of jobs fetched by this query: SELECT id from jobs WHERE status = "QUEUED" ORDER BY created_at ASC LIMIT 1; # Do the actual update, otherwise abort (i.e. ROLLBACK?) UPDATE jobs SET status="RUNNING" # HERE: Not sure how to make this conditional on the previous ID # WHERE id = <ID from the previous SELECT> COMMIT;
당신이 원하는 것이 무엇인지 아직 명확하지 않습니다. 하지만 귀하의 작업이 다음
QUEUED
作业。将其状态设置为RUNNING
을 찾아 해당 ID를 선택한다고 가정해 보겠습니다.단일 스레드 환경에서는 코드만 사용하면 됩니다. 선택한 ID를 애플리케이션 코드의 변수로 추출하여 WHERE 절의 UPDATE 쿼리에 전달합니다. write 문이 하나만 있으므로 트랜잭션도 필요하지 않습니다. SQLscript에서 이를 모방할 수 있습니다.
현재 상태는 다음과 같습니다.
으아아아대기 중인 다음 작업(id=2)을 시작하려고 합니다.
으아아아당신은 얻을 것이다
으아아아마지막 선택부터 시작합니다. 테이블의 상태는 다음과 같습니다:
으아아아DB Fiddle에서 보기
작업을 시작하는 프로세스가 여러 개 있는 경우 이를 방지하려면
FOR UPDATE
锁定该行。但可以使用LAST_INSERT_ID()
를 사용해야 합니다.위 상태부터 시작하여 작업 2가 이미 실행 중입니다.
으아아아얻을 수 있는 것:
으아아아새로운 상태:
으아아아DB Fiddle에서 보기
UPDATE 문이 어떤 행에도 영향을 미치지 않은 경우(대기 중인 행 없음),
ROW_COUNT()
将为0
.내가 인식하지 못하는 위험이 있을 수 있지만 실제로는 그렇게 접근하지도 않습니다. 차라리
으아아아jobs
테이블에 더 많은 정보를 저장하고 싶습니다. 간단한 예:그리고
으아아아이제 실행 중인 작업은 특정 프로세스에 속하므로
를 사용하여 간단히 선택할 수 있습니다. 으아아아더 알고 싶을 수도 있습니다.
queued_at
、started_at
、finished_at
.이번 주에 저는 귀하의 사례와 매우 유사한 것을 구현할 예정입니다. 여러 작업자가 각각 작업할 행 집합에서 "다음 행"을 가져옵니다.
의사 코드는 다음과 같습니다:
으아아아경합 조건(예: 여러 작업자가 동일한 행을 가져오려는 경우)을 피하려면
FOR UPDATE
을 사용하는 것이 중요합니다.에 대한 자세한 내용은 https://dev.mysql.com/doc/refman/8.0/en/select-into.html
SELECT ... INTO
을 참조하세요.