2012-01-19 4 views
-1

이 문제를 해결하는 방법에 대한 아이디어를 찾고 있습니다. 거래가 있습니다 :브레인 스토밍 솔루션 --- 이중 이메일 전송

우리는 디렉토리에 앉아있는 파일을 산발적으로 보내고 있습니다. 우리 측에서는 들어오는 파일에 대한 디렉터리를 모니터링하는 Windows 서비스를 제공합니다. 서비스가 실행되고 파일을 찾으면 코드를 실행하여 해당 파일 처리를 시작합니다. 디렉토리는 한 번에 1 ~ n 개의 파일을 가질 수 있습니다. 예를 들어 디렉토리에 1000 개의 파일이 있고 Windows 서비스에서 해당 파일을보고 데이터베이스에 데이터를 저장하고 전자 메일을 보내는 프로세스를 시작합니다.

프로세스는 멀티 스레드 및 비동기 적으로 실행됩니다. 파일을 가져 와서 데이터베이스에 데이터를 넣은 다음 다른 사람에게 전자 메일을 보냅니다. 여기서 문제는 두 프로세스가 실행 중이고 둘 모두가 동일한 코드를 사용하고있을 때 때로는 동일한 사람에 대해 두 개의 전자 메일이 생성 될 수 있다는 것입니다. 방법은 다음과 같습니다 :

  1. 데이터베이스로 이동하여 우리가 가지고있는 연락처가 있는지 확인하십시오.
  2. 그는 거기에 있습니다. 좋아요, '이메일 신고 열'에 이메일이 전송 되었습니까?
  3. 아니요, 알았습니다. 그에게 이메일을 보내고 '이메일 플래그 열'을 YES (불량)로 표시하십시오.

무슨 일이 일어나고있는 것은 2 개의 스레드가 동시에이 방법을 사용하고 코드를 동시에 읽는 것입니다. 둘 다 데이터베이스를 살펴보고 '전자 메일 플래그 열'이 NO인지 확인합니다. 그런 다음 전자 메일을 보내서 열을 YES로 표시합니다. 그러나 이렇게 빠른 속도로 일어나기 때문에 스레드 (A)는 스레드 (B)가 열을 읽기 전에 DB 열을 표시 할 기회를 얻지 못했습니다.

두 스레드가이 메서드에서 등을 맞대고 있다면 '기다리는'코드를 작성하는 것에 대해 생각해 보았습니다. LOCK처럼. 그러나 우리는 그렇게 할 수 없습니다. 내가 가진 유일한 해결책은 이메일을 보내지 않는 것입니다. 특정 시간대에 실행되는 콘솔 앱을 보유하고 있으며 해당 열에 0 (NO)을 가진 사람들에게 전자 메일을 보냅니다. 전자 메일이 전송되면 열을 1 (예)로 표시합니다.

그것은 최고의 솔루션이 아닐 수도 있습니다. 그래서 저는 여러분을 유령의 무서운 똑똑한 사람들로 하여금 섹시한 해결책을 생각하게 도와주고 있습니다.

+0

데이터베이스를 읽고 업데이트하는 경우 트랜잭션을 사용하는 것이 자신과 같은 시나리오에 대한 일반적이며 입증 된 솔루션입니다. – Filburt

+1

BTW : SO는 토론 포럼이 아닙니다. 그것은 질의 응답 사이트입니다. –

답변

1

자물쇠가 필요합니다.

한 가지 방법은 처리를 시작하기 전에 프로세스가 해당 프로세스의 개인 폴더로 전자 메일을 이동하도록하는 것입니다. 하나의 프로세스 만 파일을 이동할 수 있습니다. 자물쇠가있어.

편집

데이터베이스에서 잠금을 설정하기 위해 데이터베이스를 사용하기로 결정한 경우, 조심.

Windows Vista, 7 또는 Server 2008에서 트랜잭션 파일 시스템에 도달하기 위해 특별한 PInvokes를 수행하지 않는 한 트랜잭션을 파일 시스템으로 확장하는 데 항상 문제가 발생할 수 있습니다.

0

여러 프로세스와 동기화 문제가있는 경우 일종의 중앙 잠금이 필요합니다. 그렇지 않으면 문제를 해결할 수 없습니다. 어떻게 든 그들은 의사 소통을해야합니다.

설명대로 프로세스를 수행 할 수 없다면 중앙 '동기화'서버를 사용해보십시오. Redis은 작업을 수행하며 원자 키 연산을 수행합니다.파일을 열 때 즉시 키를 설정하고 "이 파일을 처리했으며 ID가 X 인 프로세스"라는 키를 설정하는 프로세스를 가져옵니다. 다른 사람이 해당 파일을 잠근 경우 프로세스를 취소합니다. 파일을 열 때 잠금을 설정하는 사이에 더 많은 충돌 문제가 발생하지 않도록 메일을 보내기 전에 다시 확인하십시오.

특정 시간이 지나면 자동으로 만료되도록 키를 설정할 수 있습니다.

1

SP를 사용하거나 select 트랜잭션을 같은 트랜잭션으로 옮기는 것만으로 전자 메일 플래그를 읽을 수 있습니다. 예를 들어 전자 메일 전송에 실패하면 항상 0으로 되돌릴 수 있습니다.

+1

SELECT xxx FROM yyy ** FOR UPDATE **는 데이터베이스에 잠금을 설정합니다. –

+0

hummmm, USING (C#) 또는 트랜잭션 블록에 SQL 쿼리를 넣는 것이 트릭 일 수 있습니다 .... ....? – user1158555

+0

C#'using'은 실제로 데이터베이스 동시성과는 아무런 관련이 없습니다. 실제로 데이터베이스 트랜잭션은 트릭을 수행해야합니다. –

관련 문제