>  Q&A  >  본문

MySQL의 동시 작업자 스레드를 사용한 원자적 읽기 및 업데이트

MySQL 테이블을 동시에 읽고 쓸 수 있는 작업자가 여러 명 있다고 가정해 보겠습니다(예: jobs). 각 작업자의 임무는 다음과 같습니다.

  1. 가장 오래된 已排队 채용정보 찾기
  2. 상태를 RUNNING
  3. 로 설정하세요.
  4. 해당 아이디를 돌려주세요.

작업자가 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;

P粉239164234P粉239164234303일 전442

모든 응답(2)나는 대답할 것이다

  • P粉536909186

    P粉5369091862023-12-22 09:14:00

    당신이 원하는 것이 무엇인지 아직 명확하지 않습니다. 하지만 귀하의 작업이 다음 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_atstarted_atfinished_at.

    회신하다
    0
  • P粉635509719

    P粉6355097192023-12-22 00:24:50

    이번 주에 저는 귀하의 사례와 매우 유사한 것을 구현할 예정입니다. 여러 작업자가 각각 작업할 행 집합에서 "다음 행"을 가져옵니다.

    의사 코드는 다음과 같습니다:

    으아아아

    경합 조건(예: 여러 작업자가 동일한 행을 가져오려는 경우)을 피하려면 FOR UPDATE을 사용하는 것이 중요합니다.

    에 대한 자세한 내용은 https://dev.mysql.com/doc/refman/8.0/en/select-into.htmlSELECT ... INTO을 참조하세요.

    회신하다
    0
  • 취소회신하다