2008-10-03 7 views
1

팀 구성원이 웹 페이지의 링크를 두 번 클릭하면 브라우저에서 두 개의 요청을 보내면 동일한 레코드가 두 번 데이터베이스에 삽입되는 기존 사내 시스템의 문제가 발생했습니다. 경쟁 조건; 마지막으로 실행할 키가 기본 키 위반으로 실패합니다. 여러 솔루션과 해킹이 제안하고 논의되었다 :이중 삽입 해상도를 두 번 클릭 하시겠습니까?

  1. 를 사용하여 자바 스크립트를 웹 페이지에 첫 번째 클릭에 대한 링크를 비활성화하여 두 번째 클릭을 완화 할 수 있습니다. 이것은 문제의 발생을 줄이기위한 빠르고 쉬운 방법이지만 완전히 제거하지는 못합니다.

  2. 트랜잭션의 서버 측에서 요청 실행을 감싸십시오. 이것은 문제가되는 테이블의 서버로드 및 잠금 레벨로 인해 너무 비싸다고 판단되었습니다.

  3. 실패한 삽입으로 발생하는 1 차 키 예외를 찾아서 식별하여 먹습니다. 이것은 (a) 데이터베이스 종속적 예외의 뉘앙스를 알아야하고, (b) 합법적 인 데이터베이스 오류를 로깅/처리하지 않을 수있는 벤더 종속 (vendor-in)의 단점이 있습니다.

  4. 삽입이 실패한 경우 레코드를 업데이트하고 업데이트 결과를 확인하여 영향을받는 1 레코드가 반환되는지 확인하여 # 3의 확장.

다른 옵션은 고려되지 않았습니까? 간과 한 옵션의 장단점이 있습니까? 모든 악의 더 작은 것인가?

답변

1

동기화 토큰 패턴을 구현해야합니다.

작동 방식 : 각 요청에 대해 서버에서 값 (토큰)이 생성됩니다. 이 동일한 토큰은 양식 제출에 포함되어야합니다. 요청을 받으면 서버 토큰과 클라이언트 토큰이 비교되고 동일한 경우 레코드를 계속 추가 할 수 있습니다. 그런 다음 서버 측 토큰이 재생성되므로 이전 토큰을 포함하는 후속 요청은 실패합니다.

this page의 절반 길이에 대한 자세한 설명이 있습니다.

당신이 사용하는 기술은 확실하지 않지만 Struts는이 패턴에 대해 프레임 워크 수준의 지원을 제공합니다. 예를 참조하십시오 here

+0

이것이 가장 잘 표현 된 응답 인 것으로 보이지만 토큰 검사와 새 토큰 생성 사이에는 여전히 경쟁 조건이 있습니다. 그것은 어떻게 든 동기화되어야합니다. –

+0

새 토큰이 각 페이지보기에서 다시 생성되고 성능 저하없이 잠길 수있는 일종의 데이터베이스에 저장되는 경우가 아닙니다. 이제 데이터베이스를 잠글 수 있고 값이 이미 사용되었는지 확인한 다음 오류가 발생하지 않았는지, 사용되지 않았 으면 플래그를 사용하여 완료했다고 할 수 있습니다 –

5

숨겨진 필드의 페이지에 고유 한 식별자를 추가하십시오. 주어진 고유 ID로 하나의 응답 만 수락하십시오.

+0

입니다 - 서버 팜의 그들은 모두이 식별자의 인식해야 할 것입니다 그리고 그들은 모두 동기화해야하고 것 두 개의 요청이 두 개의 서로 다른 서버에 걸쳐 균형 잡혀 있다면 경쟁 조건이 없었습니다. –

+0

고유 식별자가 데이터베이스 삽입의 기본 키인 경우 데이터베이스 무결성이이를 처리합니다. –

0

이미 귀하의 질문에 대한 답변이있는 것 같습니다. # 1이 유일한 실행 가능한 옵션 인 것 같습니다.

그렇지 않으면 데이터 무결성을 데이터베이스 수준에서 처리해야하지만 데이터베이스에서 왕복을 피하기 위해 코드에서 추가 검사 (예 : 명시 적 트랜잭션)를 수행하면 성능이 향상 될 수 있습니다.

2

서버 상태를 수정하라는 GET 요청을 잘못 사용하는 것처럼 들리지만 (반드시 그런 것은 아니지만) 소리가 들립니다. 상황에 따라 적절하지 않을 수도 있지만, 링크를 POST 형식으로 변환하는 것을 고려해야한다고 명시해야합니다.

0

REF 동기화 토큰 패턴을 구현해야합니다.

이 서버 측에서 많은 오버 헤드를 추가 자바 스크립트/HTML하지 JAVA