2009-08-13 6 views
2

웹 사이트에 기사가 있고이 기사에 대한보기 수를 추적하고 싶다고 가정 해 봅니다. 아티클 테이블에는 PK ID - int, Name - nvarchar (50) 및 ViewCount - int가 있습니다. 페이지를 볼 때마다 ViewCount 필드가 증가합니다. 필드를 업데이트 할 때 충돌이 걱정됩니다. 내가 좋아하는 트랜잭션와의 sproc에서 실행할 수 있습니다증분 된 DB 필드

CREATE PROCEDURE IncrementView 
(
    @ArticleID int 
) 
as 

BEGIN TRANSACTION 

UPDATE Article set ViewCount = ViewCount + 1 where ID = @ArticleID 

IF @@ERROR <> 0 
BEGIN 
    -- Rollback the transaction 
    ROLLBACK 

    -- Raise an error and return 
    RAISERROR ('Error Incrementing', 16, 1) 
    RETURN 
END 

COMMIT 

나의 두려움은 내가이 모델에서 계산되지 않는 페이지 뷰와 끝까지 갈거야 것입니다. 다른 가능한 솔루션은 로그 유형의 모델로 실제로 기사에 대한보기를 기록하고 기사에 대한 조회수에 대한 데이터를 얻기 위해 함수와보기의 조합을 사용합니다.

답변

2

아마도 더 나은 모델은 어딘가에 앱에서 매시간 조회수를 캐시 한 다음 배치 스타일 프로세스에서 업데이트하는 것입니다.

- 편집 :

더 정교하려면, 당신을 위해 간단한 모델이 될 수있다 :

  1. 각 페이지로드는, 주어진 페이지, 정적 해시 맵을 증가. 또한 각로드에서 '마지막 업데이트'이후 충분한 시간이 경과했는지 확인하고 업데이트 된 경우 업데이트를 수행하십시오.

  2. 까다 로워서 기본 값을 asp.net 캐시 (http://msdn.microsoft.com/en-us/library/aa478965.aspx)에 넣고 시간이 초과되면 [링크에 설명 된대로 캐시 제거 핸들러를 구현하십시오.] 업데이트를 수행하십시오. 한 시간 동안 시간 초과를 설정하십시오.

두 모델 모두 정적 페이지 맵을 사용합니다. 이 각각의 뷰를 업데이트 할 것이고, 현재의 '라이브'카운트를 얻기 위해이 값과 캐시 된 db 값을 사용할 것이다.

+0

아니, 실시간이어야합니다. 이 사이트를 살펴 본다면 조회수가 실시간으로 작동합니다. – Darthg8r

+0

그것은 실시간으로 표시 될 수 있습니다. 즉, _database_ 실시간에는 표시되지 않습니다. 변수는 정적 일 수 있습니다. –

+0

+1 흠, 나쁘지 않습니다. 당신은 내가 asp.net을 사용하고 있다고 가정했다. .. 운 좋게, 나는있다. 모델에서 lock()을 사용하여 정적 해시/캐시 항목을 안전하게 만들 수 있습니다. – Darthg8r

2

데이터베이스는 원자 적으로 한 자릿수의 증분을 처리 할 수 ​​있어야합니다. 충돌이있을 수있는 경우 큐의 쿼리를 순서대로 처리해야합니다. 볼륨이 충분하면 더 큰 문제는 같은 행에 대한 모든 쓰기를 처리하는 것입니다. 각 쓰기는 그 뒤에 읽 기 및 쓰기를 차단합니다. 걱정이된다면 SQL 업데이트를 연속적으로 호출하고 수백 개의 동시 스레드 (하드웨어가 포화 될 때까지 스레드 증가)로 실행하는 간단한 프로그램을 만들 것입니다. 시도가 최종 결과인지 확인하십시오.

일괄 업데이트를 캐시하고 /하거나 일괄 처리를 수행하는 메커니즘을 찾는 것은 우승자처럼 들릴 수 있습니다.

야곱

+0

나는 db를 해머하고 출력을 검사하는 테스트 프로젝트에 대한 아이디어를 좋아한다. – Darthg8r

0

당신은 SQL Server의 단일 업데이트 문 내에서 동시성에 대해 걱정할 필요가 없습니다.
두 번째 사용자가 10 분의 1 초에 테이블을 쳤을 까봐 걱정된다면 하루에 864,000 초가 있다는 것을 명심하십시오. 기사를 제공하는 페이지에서 문제가되는 것처럼 들리는 것은 아닙니다.

0

두려움이 없습니다!

이 업데이트는 단일 (원자 단위) 트랜잭션으로, '충돌'을 얻을 수 없습니다. IncrementView에 대한 5,000,000 건의 호출이 모두 똑같은 순간에 데이터베이스에 도달하더라도 일련의 큐 형태로 처리됩니다. 즉, 데이터베이스 엔진을 사용하여 일관성을 유지합니다. 각 호출은 행에 대해 독점적 인 업데이트 잠금을 얻게되므로 (적어도) 현재 쿼리가 커밋 될 때까지 후속 쿼리가 행을 업데이트 할 수 없습니다.

BEGIN TRAN ... COMMIT를 사용할 필요조차 없습니다. 업데이트가 실패하면 롤백 할 수 없습니다.

앱 캐싱이 필요하지 않습니다.이 업데이트가 시간이 오래 걸릴 이유가 없으므로 앱 성능에 영향을주지 않아야합니다. [비교적 ​​잘 설계되었다고 가정하십시오]