가속 데이터베이스 복구 [ADR] (2) Version Store 운영 및 모니터링

Database/SQL Server / /
728x90

SQL Server가 자동으로 Version Store size를 자동으로 관리하고 저장된 행을 필요 이상으로 오래 유지하지 않도록 하는 Thread를 작동한다.

하지만 여기에도 문제가 있는데 SQL Server의 정리 Thread가 더 Version Store가 더 많은 용량이 필요하다고 판단하여 tempdbsize를 키우려고 할 때 디스크가 꽉 차서 더 이상 늘릴 수 없을 경우 RCSI(또는 SI)이 포함된 쿼리는 모두 실패할 것이다.

따라서 지속적으로 운영 및 모니터링을 해줄 필요성이 있다.

Windows Perfmon 에서 다음과 같은 항목을 모니터링 한다.

l  Transactions: Free space in tempdb

-       tempdb의 여유 공간의양을 모니터링 함으로써 Row Versioning을 유지하는데 문제가 발생할지 않도록 사용자가 tempdb를 설정한다.

l  Transactions: Version store Size

-       해당 항목은 Version Store SizeKB 단위로 모니터링 한다.

-       해당 항목을 통해 tempdb의 여유 공간을 설정하는 자료로 이용될 수 있다.

l  Transactions: Version generation rate

-       초 당 Version Store KB 단위로 얼마나 생성하는지에 대한 항목

l  Transactions: Version cleanup rate

-       초 당 Version Store KB 단위로 얼마나 제거하는지에 대한 항목

l  Transactions: Update conflict ratio

-       업데이트 충돌이 발생된 Snapshot Transaction의 비율을 나타내는 항목

-       업데이트 충돌이 발생된 Snapshot Transaction / 전체 발생된 Snapshot Transaction

l  Transactions: Longest transaction running time

-       RCSI(또는 SI)가 설정된 Transaction 중 가장 실행 시간이 길었던 Transation 시간

-       해당 시간을 통해 tempdb의 최대 크기를 설정하는데 자료로 사용

l  Transactions: Snapshot transactions

-       총 진행된 Snapshot Transaction의 수를 나타내는 항목

 

먼저 AdventureWorks2019.Sales.SalesOrderDetail 를 기반으로 테스트 데이터 생성 후

RCSI 사용 옵션을 설정한다.

SELECT  *

INTO    AdventureWorks2019.dbo.vs_test_tbl

FROM    AdventureWorks2019.Sales.SalesOrderDetail

 

ALTER DATABASE AdventureWorks2019 SET SINGLE_USER WITH ROLLBACK IMMEDIATE

ALTER DATABASE AdventureWorks2019 SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT

ALTER DATABASE AdventureWorks2019 SET MULTI_USER

 

이 후 Profiler PerfMon을 설정하고 테스트를 진행했다.

Profiler BatchStartEnd만 수집하고 PerfMon은 위의 사항을 모두 수집했다.

다음과 같은 구문으로 Update 작업을 발생하여 Snapshot이 발생되도록 한다.

UPDATE  AdventureWorks2019.dbo.vs_test_tbl

SET     UnitPriceDiscount = 99.99

 

다음과 같은 결과를 확인해 볼 수 있다.


 

UPDATE 구문이 발생되면서 Version Store에 데이터가 생성되면서 Version generation rate 가 상승되었다가 생성이 완료되면 줄어들고 Version store Size 가 늘어나면서 Free space in tempdb가 감소하는 것을 볼 수 있다.

위와 같이 수집기로 모니터링이 가능하고 관련 DMV 또한 제공하고 있다.

l  sys.dm_tran_version_store

-        Version Store에 저장된 모든 버전 레코드를 표시

-        transaction_sequence_num : XSN

-        version_sequence_num : Transaction 내에 고유한 번호로 transaction_sequence_num가 변경될 때마다 1부터 시작

-        database_id : 데이터베이스 고유 번호

-        rowset_id : Index heap의 행 집합의 고유 ID

-        status : Version이 지정된 행이 2개 레코드로 분한되었는지 여부 0이면 1개 페이지에 저장되어 있고, 1이면 지정된 행이 2개의 페이지에 걸쳐 저장되어 있다.

-        min_length_in_bytes : 행의 최소 길이(Byte)

-        record_length_first_part_in_bytes : Version Store 행에서 첫 번째 부분의 길이(Byte)

-        record_image_first_part : 행이 이진 이미지 형태 일 때 Version Store 행에서 첫 번째 부분의 이미지

-        record_length_second_part_in_bytes : Version Store 행에서 두 번째 부분의 길이(Byte)

-        record_image_second_part : 행이 이진 이미지 형태 일 때 Version Store 행에서 두 번째 부분의 이미지

l  sys.dm_tran_top_version_generators

-        Version Store에서 가장 많은 부분을 차지하는 개체 정보를 리턴

-        database_id : 데이터베이스 고유 번호

-        rowset_id : Index heap의 행 집합의 고유 ID

-        aggregated_record_length_in_bytes : 한 행의 길이의 합계 (Byte)

l  sys.dm_tran_active_snapshot_database_transactions

-        Row Versioning 되어 있는 모든 Active Transaction 정보

-        transaction_id : Transaction 고유 번호

-        transaction_sequence_num : XSN

-        commit_sequence_num : Commit 완료 또는 중지된 시점을 나타내는 번호

-        is_snapshot : 스냅샷 격리 여부

-        session_id : Transaction을 시작한 Session ID

-        first_snapshot_sequence_num : Snapshot을 생성할 때의 가장 낮은 XSN

-        max_version_chain_traversed : Version Chain의 최대 길이

-        average_version_chain_traversed : Version ChainRow Version

-        elapsed_time_seconds : TransactionXSN을 발급 받고서 경과된 시간

 

다음과 같이 2개의 행을 무한 루프에서 업데이트하도록 하면

WHILE 1=1

BEGIN

    UPDATE  AdventureWorks2019.dbo.vs_test_tbl

    SET     UnitPriceDiscount = 99.99

    WHERE   SalesOrderID IN (43659,43661)

 

    WAITFOR DELAY '00:00:01'

END

 

 

다음과 같이 해당 Session에서 진행된 Snapshot Transaction의 정보를 조회 할 수 있고

SELECT  transaction_sequence_num

    ,   commit_sequence_num

    ,   is_snapshot

    ,   t.session_id

    ,   first_snapshot_sequence_num

    ,   max_version_chain_traversed

    ,   elapsed_time_seconds

    ,   CASE transaction_isolation_level

        WHEN 0 THEN 'None'

        WHEN 1 THEN 'ReadCommitted'

        WHEN 2 THEN 'ReadUncommitted'

        WHEN 3 THEN 'RepeatableRead'

        WHEN 4 THEN 'Serializable'

        WHEN 5 THEN 'Snapshot'

        END AS transaction_isolation_level

FROM    sys.dm_tran_active_snapshot_database_transactions t

INNER   JOIN sys.dm_exec_sessions s ON t.session_id = s.session_id

 

아래와 같이 현재 Version Store에 저장된 데이터의 정보를 확인할 수 있으며

SELECT  A.transaction_sequence_num

    ,   A.version_sequence_num

    ,   A.rowset_id

    ,   B.name

FROM    sys.dm_tran_version_store AS A

INNER   JOIN sys.databases AS B

ON      A.database_id = B.database_id

 

아래와 같이 해당 행의 Version 정보 중 가장 용량을 사용할 때의 정보를 조회할 수 있다.

(위의 루프문이 2개의 행을 update 하기 때문에 2개의 행이 조회된다.)

SELECT  A.database_id

    ,   A.aggregated_record_length_in_bytes

    ,   B.name

FROM    sys.dm_tran_top_version_generators AS A

INNER   JOIN sys.databases AS B

ON      A.database_id = B.database_id

 

 

참조

https://www.red-gate.com/simple-talk/databases/sql-server/t-sql-programming-sql-server/row-versioning-concurrency-in-sql-server/

https://sqlrambling.net/2015/09/11/monitoring-versioning/

https://docs.microsoft.com/ko-kr/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-active-snapshot-database-transactions-transact-sql?view=sql-server-ver15

https://docs.microsoft.com/ko-kr/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-version-store-transact-sql?view=sql-server-ver15

https://docs.microsoft.com/ko-kr/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-version-store-transact-sql?view=sql-server-ver15

728x90
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기