문제

제가 한동안 구축 한 응용 프로그램 내에서 sqlalchemy를 ORM으로 사용하고 있습니다.

지금까지는 구현 및 사용하기가 상당히 고통스러운 ORM 이었지만, 최근에 작업중 인 기능은 MySQL과 Python에서 구축 한 영구 및 분산 큐 (List & Worker) 스타일 구현이 필요합니다.

스케일링 된 환경에서 테스트 할 때까지 모두 잘 작동했습니다. 나는 innodb 행 레벨 잠금을 사용하여 각 행이 한 번만 읽히도록했는데 행이 잠겨있는 동안 an '을 업데이트합니다.in_use'가치, 다른 사람들이 항목을 잡지 않도록하십시오.

MySQL은 PostGre 또는 Oracle과 같은 "nowait"방법을 제공하지 않기 때문에 작업자 스레드가 매달려 잠금 행이 사용할 수있을 때까지 잠금 문제가 발생합니다.

이 제한을 극복하기 위해 필요한 모든 처리를 단일 진술에 넣고 ORM을 통해 실행하려고 노력했습니다. execute() 방법은 Sqlalchemy가 쿼리 결과를 반환하는 것을 거부하고 있습니다.

여기 예입니다.

내 SQL 문은 다음과 같습니다.

SELECT id INTO @update_id FROM myTable WHERE in_use=0 ORDER BY id LIMIT 1 FOR UPDATE;
UPDATE myTable SET in_use=1 WHERE id=@update_id;
SELECT * FROM myTable WHERE id=@update_id;

이 코드를 콘솔에서 실행합니다.

engine = create_engine('mysql://<user details>@<server details>/myDatabase', pool_recycle=90, echo=True)
result = engine.execute(sqlStatement)
result.fetchall()

이 결과를 얻기 위해서만

[]

데이터베이스에서 업데이트가 적용되는 것을 볼 수 있기 때문에 명세서가 실행되고 있다고 확신하며 MySQL 터미널 또는 기타 도구를 통해 실행되면 수정 된 행을 반환합니다. 반환 된 행을 인정하고 싶지 않은 Sqlalchemy 인 것 같습니다.

ORM이 응답을 선택할 수 있도록해야 할 구체적인 작업이 있습니까?

건배

도움이 되었습니까?

해결책

3 쿼리를 실행했으며 MySQLDB는 각각의 결과 세트를 만듭니다. 첫 번째 결과를 가져 와서 호출해야합니다 cursor.nextset(), 두 번째 등을 가져 오십시오.

이것은 귀하의 질문에 답변하지만 잠금 문제를 해결하지 않기 때문에 귀하에게 유용하지 않습니다. 업데이트가 먼저 작동하는 방법을 이해해야합니다. 트랜잭션이 끝날 때까지 반환 된 행을 잠그십시오. 긴 잠금 장치를 피하려면 가능한 한 짧게 만들어야합니다. SELECT ... FOR UPDATE, UPDATE SET in_use=1 ..., COMMIT. 실제로 단일 SQL 문, 3에 넣을 필요가 없습니다. execute() 전화도 괜찮을 것입니다. 그러나 당신은 긴 계산 전에 커밋해야합니다. 그렇지 않으면 잠금이 너무 오래 유지되고 업데이트됩니다. in_use (오프라인 잠금)는 의미가 없습니다. 그리고 당신은 ORM을 사용하여 똑같은 일을 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top