MySQL을 기본 격리 수준 (반복 가능 읽기)에서 실행 중입니다.중복 키 오류 삽입 후 SELECT가 실패 함
파이썬 코드는 두 개의 동시 프로세스 내에서 동시에 실행할 수있는 트랜잭션을 관리하기 위해 sqlalchemy를 사용합니다.
c.begin();
# this SELECT establishes the transaction snapshot from which all other SELECTs will read data
c.execute("SELECT something FROM sometable;")
try:
c.execute("INSERT INTO othertable (unique_key) VALUES (1)")
except sqlalchemy.exc.IntegrityError as e:
code, msg = e.orig
if code != 1062:
raise
# duplicate key: another transaction commited the above INSERT so I can't rely on LAST_INSERT_ID
rows = c.execute("SELECT * FROM table WHERE unique_key=1")
inserted_id = None
for id, in rows:
inserted_id = id
break
assert inserted_id is not None
else:
inserted_id = c.last_insert_id()
c.commit()
정확한 코드
분명히 좀 더 복잡한 더 많은 쿼리하지만 문제의 핵심은이 코드가 자주 예외 처리기에서 어설 명중이다.이유는이 트랜잭션이 다른 프로세스에서 동시에 실행되는 경우가 많기 때문입니다. 첫 번째 SELECT에 의해 설정된 DB 스냅 샷에 새로 삽입 된 행이 들어 있지 않기 때문에 중복 키 예외에서 트리거되는 SELECT가 실패합니다 첫 번째 SELECT 후 INSERT 전에 다른 트랜잭션에 의해 삽입되었습니다.
이제 FOR UPDATE를 사용하도록 SELECT를 변경할 수 있다는 사실을 알고 스냅 샷에 구멍을내어 삽입 된 실제 값을 읽습니다.
그러나 나는 이것이 꽤 많은 장소에서 이것을 뿌려야 할 것이기 때문에 이것을 꺼려하고 있으며, 나는 이것을 비교적 연약한 것으로 봅니다.
이 concurent 삽입물을 처리하는 데있어 좀 더 견고하고 표준이 낮고 추악하지 않은 방법이 있습니다 (처리해야하는 것은 사실입니다). 인공 업데이 트를 추가
는