해결하기 쉬운 몇 가지 가능한 시나리오와 그렇지 않은 위험한 시나리오가 있습니다.
값을 입력 한 사용자의 경우 INSERT가 문제점을 감지하기 전에 얼마 후에 동일한 SELECT를 간단한 SELECT를 입력하십시오. 이것은 한 사용자가 값을 제출하고 나중에 다른 사용자가 동일한 값을 제출하는 경우에 효과적입니다.
사용자가 코드를 한 번만 호출하여 중복 된 값 목록 (예 : {ABC, DEF, ABC})을 제출하면 응용 프로그램은 중복을 감지하고 필터링하여 오류를 발생시킬 수 있습니다. 또한 삽입 전에 DB에 고유 값이 포함되어 있지 않은지 확인해야합니다.
까다로운 시나리오는 한 사용자의 쓰기가 다른 사용자의 쓰기와 동시에 DBMS 내에 있고 동일한 값을 쓰는 경우입니다. 그렇다면 당신은 그들 사이에 경쟁 조건이 있습니다. DBMS는 선점 형 멀티 태스킹 시스템 (대부분 사용중인 시스템을 말하지는 않음)이므로 모든 작업이 실행 중 일시 중지 될 수 있습니다. 즉, user1의 작업은 기존 행이 없는지 확인한 다음 user2의 작업은 기존 행이 없는지 확인한 다음 user1의 작업은 해당 행을 삽입 한 다음 user2의 작업은 해당 행을 삽입 할 수 있습니다. 각 시점에서 작업은 개별적으로 만족하며 올바른 일을하고 있습니다. 그러나 전 세계적으로 오류가 발생합니다.
일반적으로 DBMS는 해당 값을 고정하여이를 처리합니다. 이 문제에서는 새 행을 작성하므로 아직 잠글 항목이 없습니다. 대답은 범위 잠금입니다. 제안했듯이 현재 존재 여부에 관계없이 다양한 값을 잠급니다. 일단 잠금이 해제되면 잠금이 해제 될 때까지 다른 작업에서 해당 범위에 액세스 할 수 없습니다. 범위 잠금을 얻으려면 SERIALIZABLE의 격리 수준을 지정해야합니다 . 작업을 확인한 후 다른 작업이 연속으로 몰래 발생하는 현상을 팬텀 레코드라고 합니다.
전체 응용 프로그램에서 격리 수준을 직렬화 가능으로 설정하면 의미가 있습니다. 처리량 이 줄어 듭니다. 과거에 충분히 효과가 있었던 다른 경쟁 조건은 이제 오류를 표시하기 시작할 수 있습니다. 중복 유도 코드를 실행하고 나머지 응용 프로그램은 그대로 두는 연결에서 설정하는 것이 좋습니다.
코드 기반 대안은 이전보다는 쓰기 후에 확인 하는 것입니다. INSERT를 수행 한 다음 해시 값이있는 행 수를 계산하십시오. 중복이 있으면 조치를 롤백하십시오. 이것은 약간의 잘못된 결과를 초래할 수 있습니다. 작업 1이 작업 2를 쓴 다음 작업 1이 중복을 확인하고 찾습니다. 처음이더라도 롤백됩니다. 마찬가지로 두 작업 모두 중복 및 롤백을 모두 감지 할 수 있습니다. 그러나 최소한 재시도 메커니즘을 사용하고 새로운 복제본을 사용하지 않는 메시지가 표시됩니다. 롤백은 예외를 사용하여 프로그램 흐름을 제어하는 것과 매우 유사합니다. 참고 아니라 그 모든트랜잭션의 작업은 중복 유도 쓰기뿐만 아니라 롤백됩니다. 그리고 동시성을 줄일 수있는 명시적인 트랜잭션이 있어야합니다. 해시에 대한 색인이 없으면 중복 검사가 엄청나게 느려집니다. 당신이 할 경우뿐만 아니라 독특한 하나를 만들 수 있습니다!
당신이 언급 한 것처럼 실제 솔루션은 고유 색인입니다. 이것이 유지 관리 기간에 맞는 것처럼 보입니다 (물론 시스템을 가장 잘 알고 있음). 해시가 8 바이트라고 가정하십시오. 약 1GB 인 1 억 행의 경우 경험에 따르면 합리적인 수준의 하드웨어가 이러한 많은 행을 1 ~ 2 분 안에 처리 할 수 있습니다. 중복 검사 및 제거가 여기에 추가되지만 미리 스크립팅 할 수 있습니다. 그러나 이것은 제쳐두고 있습니다.