MS-SQL Server

SQL Server 2008R2 에서의 잠금해시키 충돌 개선

고희수 2011. 3. 16. 16:39
 SQL Server 2008R2 에서의 잠금해시키 충돌 개선

 SQL Server 2008 R2에서 개선된 내용중 잠금 해시키값 충돌 개선을 위한 해시 키 알고리즘 변경에 대한 내용을 정리해 볼까 합니다.
 아시다시피 SQL Server는 잠금관리자가 잠금에 대한 제어 와 관리를 하는데요.
 행이나 페이지,테이블등을 잠금리소스로 직접 사용하지 않고 잠금해시키값으로 사용해 관리됩니다.
 이 잠금해시키값은 메모리상에서 유지되며, 실제 행이나 페이지의 경우 데이터가 가변적이고 또 클수도 있어 이를 해시키값으로

 변환해 6byte 고정된 크기로 관리하게 됩니다.

 이러한 잠금해시키값을 계산하는 알고리즘에 문제가 하나 있는데요.
 서로 다른 데이터값이 동일한 해시키값을 생성할수 있어 잠금키간에 충돌이 있을수 있습니다.
 
 아래는 테스트 예제입니다.
 CREATE TABLE test
 (a VARCHAR(3) NOT NULL, b VARCHAR(8) NOT NULL, c VARCHAR(5) NOT NULL,d integer NOT NULL)
 GO

 
CREATE UNIQUE CLUSTERED INDEX ucl ON test(a,b,c)
 GO

 
begin transaction
 INSERT test VALUES('150','00001082','00345',1)

 
select resource_type,resource_database_id, resource_description, resource_associated_entity_id,request_mode, request_type,   request_status from sys.dm_tran_locks where resource_type = 'KEY'

lockhashkey_1.jpg

 그림을 보시면 resource_description 필드에 값이 삽입된 값 '150','00001082','00345'의 조합으로 해시키값을 계산한 값입니다.    
 resource_associated_entiry_id 필드는 B-tree ID 값입니다.
 이는 sys.partitions and sys.allocation_units 를 통해서 확인할수 있습니다.

 다음쿼리를 실행하고 다시 잠금정보를 확인합니다.

 begin transaction
 INSERT test VALUES('150','00024855','00012',4)
lockhashkey_2.jpg 

 그림을 보시면 다른값을 삽입했음에도 동일한 잠금해시키값이 생성됐음을 확인할수있습니다.
 (resource_description필드 확인)
 두개의 행은 차단됐으며 두번째 삽입된 행은 block된 상태로 보여지고 있습니다. 잠금해시키값이 동일하기 때문입니다.
 이러한 잠금해시키값 충돌 문제는 쉽게 발생하지는 않는다고 합니다. 대부분 멀리 떨어져 있는 데이터간의 해시키값이 동일
 할수 있기때문이라고 합니다.

 하지만 대량데이터 로드시 충돌이슈는 여전히 가능성이 있습니다. 특히나 패키지로 동일한 대량테이블을 병렬로 로드할 경우
 교착상태까지 발생할수 있다고 합니다.(지인의 경우 대량이 아닌상황에서도 발생을 했다고 하네요. 가능성은 존재하죠.)

 이를 위해 SQL Server2008 R2에서는 해시 알고리즘을 다시 작성하게 되었는데요.
 성능저하 없이 해시처리의 한쪽에 복잡도를 더 증가시켜 동일값을 최소화하는 처리로 변경됐다고 합니다.
 실제로 위 동일한 예문을 R2에서 실행시 resource_description 키값이 다름을 확인할 수 있습니다.

 참고:

http://blogs.msdn.com/b/sqlserverstorageengine/archive/2010/01/18/improvement-in-minimizing-lockhash-key-collisions-in-sql-server-2008r2-and-its-impact-on-concurrency.aspx