SELECT ... FOR UPDATE가 동시 세션/트랜잭션이 동일한 레코드를 삽입하지 못하게하는 위의 대답은 사실이지만 진실은 아닙니다. 나는 현재 같은 문제로 싸우고 있으며 SELECT ... FOR UPDATE가 다음과 같은 이유로 해당 상황에서 거의 쓸모가 없다는 결론에 이르렀습니다 :
동시 트랜잭션/세션 또한 SELECT를 수행 할 수 있습니다 ... 매우 동일한 레코드/인덱스 값에 대해 FOR UPDATE를 수행하면 MySQL은 즉각적으로 (블로킹 (non-blocking)) 에러없이 던지는 것을 기꺼이 받아 들일 것입니다. 물론, 다른 세션이 그것을 마자 마자 세션은 더 이상 레코드를 삽입 할 수 없습니다. 귀하 나 다른 세션/트랜잭션은 상황에 대한 정보를 얻지 못하며 실제로 시도 할 때까지 안전하게 레코드를 삽입 할 수 있다고 생각합니다. 상황에 따라 삽입을 시도하면 교착 상태가 발생하거나 중복 키 오류가 발생합니다.
다른 말로 SELECT ... FOR UPDATE는 다른 세션이 해당 레코드를 삽입하는 것을 방지하지만 SELECT ... FOR UPDATE를 수행하고 해당 레코드를 찾을 수없는 경우에도 실제로 해당 레코드를 삽입 할 수 없습니다. IMHO는 "첫 번째 쿼리를 삽입 한 다음"메서드를 쓸모 없게 만듭니다.
문제의 원인은 MySQL이 에 실제로는 레코드를 잠글 수 없기 때문입니다. 두 개의 동시 세션/트랜잭션은 존재하지 않는 레코드 "FOR UPDATE"를 동시에 잠글 수 있습니다. 이는 실제로 가능하지 않아야하고 개발이 훨씬 더 어려워집니다.
이 문제를 해결하는 유일한 방법은 삽입 할 때 세마포 테이블을 사용하거나 전체 테이블을 잠그는 것입니다. 전체 테이블을 잠 그거나 세마포어 테이블을 사용하는 방법에 대한 자세한 내용은 MySQL 설명서를 참조하십시오.
그냥 내 2 센트 ...
색인이없는 항목에 대해 새 행을 추가하려면 어떻게해야합니까? 그것은 인덱스없이 전체 테이블을 잠그고 있습니까? – xLite
예, 언급하지 않았습니다. 레코드 잠금에 적합한 인덱스가없는 경우 테이블 전체가 읽기 전용이됩니다. – RandomSeed
'username' 컬럼에 'UNIQUE' 인덱스가 없으면서'user_id' 컬럼에'PRIMARY'가 있으면 어떨까요? 여전히'FOR UPDATE '로 검색하면 사용자 이름'foo '가 잠겨 있는지 확인할 수 있습니까? 내가 알아 차릴 수없는 함정이 있습니까? 예 : 'user_id'와'username' 둘 다 동시에 인덱스 ('PRIMARY'와'UNIQUE')를 가지고 있다면 잠금이 불가능하고 에러가 나거나 뭔가가 나올까요? 나는 다소 미련한 질문인데 아직도 사과하고 있습니다. 답장을 보내 주셔서 감사합니다! – xLite