2014-10-19 3 views
1

SQL Server 2012를 사용하고 있습니다.총 개수가 임계 값보다 작은 경우에만 행을 SQL Server 테이블에 삽입하십시오.

사용자를 저장하는 테이블이 있습니다. 허용되는 최대 사용자 수는 1 백만입니다. 나는 사용자를 등록하고있는 sproc을 가지고있다. 삽입 할 때 사용자 테이블의 총 행 수가 1 백만을 초과하지 않도록하고 싶습니다. 최대한의 동시성을 허용하는 메소드를 사용하는 것을 선호합니다.

나는 SERIALIZABLE의 ISOLATION LEVEL로 트랜잭션을 사용할 수 있다고 생각하고, 먼저 총 개수가 100 만 개 미만이면 행 수와 삽입 수를 계산합니다. 내 이해 SERIALIZABLE 매우 제한적이며 동시성 증가로 성능 저하가 발생할 수 있습니다.

IF(SELECT COUNT(*) FROM Users) < 100000 
BEGIN 
    INSERT INTO Users VALUES (@Name, @Email, @Password) 
END 

어떻게 총 행 수 미만 100 만 보장하지만 동시에 나는 다른 트랜잭션을 차단 방지하기 위해 최소한의 잠금을되도록 내가 원자 적으로이 작업을 수행 할 수 있습니까?

이 상황에 대한 모든 솔루션/권장 사항은 무엇입니까?

답변

4

당신은 사용자의 수를 확인하고 테이블에 삽입하기 위해 선택한 새로운 사용자의 데이터 사용 검색하는 SELECT를 만들 수 있습니다 다음 SELECT 문을 하나 개의 행을 반환합니다

INSERT INTO users (
    name, email, [password] 
) 
SELECT 
    'newUser' AS name 
    , '[email protected]' AS email 
    , 'fsfsfs' AS [password] 
FROM 
    users 
HAVING 
    COUNT(*) < 100000; 

을 할 때보다 적은있다 100000 명 이상의 사용자가있는 경우 데이터베이스에 100000 명, 레코드가 0 명입니다.

전체 문장 (INSERT..SELECT)은 각 경우에 유효하지만, SELECT 부분이 0 행을 반환하면 INSERT은 아무 것도 삽입하지 않습니다.

트랜잭션 레벨이 SERIALIZABLE 인 경우, 동시 쓰기가 서로를 방해 할 수 없음을 보증합니다. COUNT (*)는 가장 효율적인 색인/키를 사용하여 행을 계산합니다. 즉, 잠금 시간은 최소가됩니다.

전체 작업을 하나 개의 문장으로 이루어지기 때문에,이 SQL Fiddle demo

+0

Whow

INSERT

하여 SELECT의 실행과 사이 insertation을 방지 할 수 있습니다. 저 모양의 진짜 똑똑한 "남용"- 나는 심각하게 감명 준다. 필요할 때 기억하도록 이것을 표시합니다. 좋은 대답. – TomTom

+0

@Pred - 올바르게 작동하려면 SERIALIZABLE 격리 수준을 사용해야합니까? – Pradeep

+0

serializable이 너무 엄격하면'REPEATABLE READ'로 충분할 수 있습니다. 실제 시나리오에서 사용자가 장기간에 등록 할 때 이것은 중요한 문제가 아니므로 READ COMMITTED 일 수 있습니다. 그러나 앱의이 부분에이 기능이 필요하며 가능한 한 정확하게 작동해야한다면 , DBE가이 코드를 실행할 때 가장 엄격한 모드에서 작동해야합니다. – Pred

관련 문제