[문의사항]

서버 메모리 사용량 90% 임계치 초과

Svchost.exe (Eventlog, lmhosts) 메모리 사용량 증가

 

[환경]

Windows Server 2008 R2 SP1

SQL Server

 

[제안]


 

1. 모니터링 카운터

버퍼 캐시 메모리 부족을 확인하기 위해 SQLServer:Buffer Manager Buffer cache hit ratio, Page life expectancy 카운터를 모니터링 하시기 바랍니다.

아래 제시된 임계값은 일반적으로 알려진 허용 수치입니다. 절대값이 아니므로 임계값 이하라고해서 반드시 메모리가 부족한 상황은 아닙니다.

메모리 부족 판단이 어려울 경우 참고용으로 활용하실 수는 있습니다.

성능모니터(perfmon)으로 카운터를 추가해서 확인해도 관계 없습니다.

 

Buffer cache hit ratio – 캐시 적중률 (90% 이상)

SELECT (a.cntr_value * 1.0 / b.cntr_value) * 100.0 as BufferCacheHitRatio

FROM sys.dm_os_performance_counters  a

JOIN  (SELECT cntr_value,OBJECT_NAME

    FROM sys.dm_os_performance_counters 

    WHERE counter_name = 'Buffer cache hit ratio base'

        AND OBJECT_NAME = 'SQLServer:Buffer Manager') b ON  a.OBJECT_NAME = b.OBJECT_NAME

WHERE a.counter_name = 'Buffer cache hit ratio'

AND a.OBJECT_NAME = 'SQLServer:Buffer Manager'

 

Page life expectancy – 페이지 메모리 상주 시간 (300초 이상)

시간() 개념이기 때문에 무제한 증가하지도 값을 유지하지도 않습니다.

300 이상의 값까지 증가한 0으로 다시 초기화되는 상황은 정상이라고 판단해도 무방합니다.

SELECT object_name, counter_name, cntr_type

FROM sys.dm_os_performance_counters 

WHERE counter_name = 'Page life expectancy'

AND OBJECT_NAME = 'SQLServer:Buffer Manager'

 

 

2. Max Server Memory 현재 설정값 확인

sp_configure 'show advanced options', 1

go

reconfigure

go

 

sp_configure 'max server memory (mb)'

reconfigure

go

 

(아래 캡쳐에서는 2048MB(2GB) 설정됨)

 

3. Max Server Memory 설정

주의) 업무시간대에 진행하실 것을 권고 드립니다.

온라인 중에 적용 가능하지만, Plan Cache 초기화되어 적용 얼마간 CPU 사용량이 급증하고 성능이 저하될 수 있습니다.

-- ) 10GB(10240MB)로설정

sp_configure 'max server memory (mb)', 10240

reconfigure

go

 


'Microsoft > SQL' 카테고리의 다른 글

SQL Account expired date 확인 방법  (0) 2018.09.07
트랜젝션 로그 불리는 방법  (0) 2018.08.03
Disk I/O Query  (0) 2018.08.03
DBCC SHRINKFILE & Internal  (0) 2018.08.03

 

 

/*


데이터가 있는 테이블을 자가 복제 하여 트랜젝션 로그를 늘릴 수 있습니다.

해당 테스트에서 사용 하는 테이블 [AdventureWorks2012].[Person].[Person]  [AdventureWorks2012] DB 에서 용량이 가장 테이블 입니다.

sp_helpdb [DatabaseName] 로 중간 중간 파일의 용량을 확인 합니다.

 

truncate table [dbo].[Person]

*/

 

--1 단계 테이블을 생성 합니다.

SET ANSI_NULLS ON

GO

 

SET QUOTED_IDENTIFIER ON

GO

 

CREATE TABLE [dbo].[Person](

        [BusinessEntityID] [int] NULL,

        [PersonType] [nchar](2) NULL,

        [NameStyle] [bit] NULL CONSTRAINT [DF_Person_NameStyle]  DEFAULT ((0)),

        [Title] [nvarchar](8) NULL,

        [FirstName] [nvarchar](50) NULL,

        [MiddleName] [nvarchar](50) NULL,

        [LastName] [nvarchar](50) NULL,

        [Suffix] [nvarchar](10) NULL,

        [EmailPromotion] [int] NULL CONSTRAINT [DF_Person_EmailPromotion]  DEFAULT ((0)),

        [AdditionalContactInfo] [xml] NULL,

        [Demographics] [xml] NULL,

        [rowguid] [uniqueidentifier] NULL,

        [ModifiedDate] [datetime] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

 

GO

--2단계 원본 테이블에서 데이터를 가져 옵니다.

 

 

INSERT [dbo].[Person] (BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate)

SELECT BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate FROM [AdventureWorks2012].[Person].[Person]

 

--데이터 백업용 테이블을 생성 합니다.

SELECT * INTO Person2 FROM [dbo].[Person]

 

--3단계 자가 복제를 시작 합니다. 순서는 (테이블 1에 데이터 입력 -> 테이블 2 데이터 입력 -> 테이블 1 Delete ) 입니다.

 

DECLARE @int int

SET @int = 0

WHILE (@int < 5)

BEGIN

 

INSERT [dbo].[Person] (BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate)

SELECT BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate FROM [dbo].[Person2]

 

INSERT [dbo].[Person2] (BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate)

SELECT BusinessEntityID, PersonType, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, EmailPromotion, AdditionalContactInfo, Demographics, rowguid, ModifiedDate FROM [dbo].[Person]

 

DELETE [dbo].[Person]

 

SET @int = @INT +1

 

END

 

/*

 

 

(19972 행이 영향을 받음)

 

(39944 행이 영향을 받음)

 

(39944 행이 영향을 받음)

 

(59916 행이 영향을 받음)

 

(59916 행이 영향을 받음)

 

(59916 행이 영향을 받음)

 

(119832 행이 영향을 받음)

 

(119832 행이 영향을 받음)

 

(119832 행이 영향을 받음)

 

(239664 행이 영향을 받음)

 

(239664 행이 영향을 받음)

 

(239664 행이 영향을 받음)

 

(479328 행이 영향을 받음)

 

(479328 행이 영향을 받음)

 

(479328 행이 영향을 받음)

 

 

sp_helpdb [SUNY]

SUNY    1       C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\SUNY.mdf        PRIMARY 1583104 KB     Unlimited      1024 KB data only

SUNY_log       2       C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\SUNY_log.ldf   NULL    4632576 KB     2147483648 KB  10%        log only

 

*/

 

 

*/


[오류 사항]

  • 오류 : 오류 메시지는 SQL Server I/O 대한 병목 현상을 나타냅니다.
  • sql server has encountered 1 occurrence(s) of i/o requests taking longer than 15 seconds to complete
  • autogrow of file 'templog' in database 'tempdb' was cancelled by user or timed out after 117437ms
  • 담당자: 김석수 책임
  • 시간: 2시간

 

 

[추후 동일 증상 발생 확인 사항]

  1. 현재 대기 보류 중인 I/O 확인 합니다.

SELECT SUM(pending_disk_io_count) AS [Number of pending I/Os] FROM sys.dm_os_schedulers

 

  1. 1 쿼리에서 보고 I/O 카운터에 대하여 세부 사항을 확인 합니다.
  • IO_Pending 값이 0 이면 SQL Server 아직 I/O 처리 하지 않은 입니다.
  • IO_Pending 값이 1 이면 Windows 에서 아직 I/O 처리 하지 않은 입니다.

SELECT *  FROM sys.dm_io_pending_io_requests

 

  1. 보류 중인 I/O 통해서 디스크 병목 현상을 확인 합니다.

SELECT DB_NAME(mf.database_id) AS [Database] , mf.physical_name ,r.io_pending , r.io_pending_ms_ticks , r.io_type , fs.num_of_reads , fs.num_of_writes

     FROM sys.dm_io_pending_io_requests AS r INNER JOIN sys.dm_io_virtual_file_stats(NULL, NULL)

                                                                 AS fs ON r.io_handle = fs.file_handle INNER JOIN sys.master_files

                                           AS mf ON fs.database_id = mf.database_id

     AND fs.file_id = mf.file_id ORDER BY r.io_pending , r.io_pending_ms_ticks DESC ;

 

  1. I/O 유발 쿼리를 찾습니다.

select top 5 (total_logical_reads/execution_count) as avg_logical_reads,

                   (total_logical_writes/execution_count) as avg_logical_writes,

           (total_physical_reads/execution_count) as avg_physical_reads,

           Execution_count, statement_start_offset, p.query_plan, q.text

from sys.dm_exec_query_stats

      cross apply sys.dm_exec_query_plan(plan_handle) p

      cross apply sys.dm_exec_sql_text(plan_handle) as q

order by (total_logical_reads + total_logical_writes)/execution_count Desc

 

  1. 테이블 당 인덱스 사용 통계 / 테이블 가장 많은 I/O 작업을 유발하는 테이블을 확인 합니다.

SELECT d.name as [Database],  OBJECT_NAME(S.[OBJECT_ID]) AS [OBJECT NAME],         

I.[NAME] AS [INDEX NAME],         

USER_SEEKS,         

USER_SCANS,         

USER_LOOKUPS,         

USER_UPDATES

FROM     SYS.DM_DB_INDEX_USAGE_STATS AS S         

INNER JOIN SYS.INDEXES AS I ON I.[OBJECT_ID] = S.[OBJECT_ID]              

AND I.INDEX_ID = S.INDEX_ID

Join sys.Databases d on s.database_id = d.database_id

WHERE    OBJECTPROPERTY(S.[OBJECT_ID],'IsUserTable') = 1

Order by USER_SEEKS + USER_SCANS + USER_LOOKUPS + USER_UPDATES desc

 

 

SELECT d.name, t.name, OBJECT_NAME(A.[OBJECT_ID]) AS [OBJECT NAME],      

 I.[NAME] AS [INDEX NAME],      

  A.LEAF_INSERT_COUNT,       

  A.LEAF_UPDATE_COUNT,       

  A.LEAF_DELETE_COUNT

 

FROM   SYS.DM_DB_INDEX_OPERATIONAL_STATS (NULL,NULL,NULL,NULL ) A       

INNER JOIN SYS.INDEXES AS I          ON I.[OBJECT_ID] = A.[OBJECT_ID]  

join sys.tables t on i.object_id = t.object_id     

join sys.databases d on a.database_id = d.database_id

AND I.INDEX_ID = A.INDEX_ID WHERE  OBJECTPROPERTY(A.[OBJECT_ID],'IsUserTable') = 1

order by A.LEAF_INSERT_COUNT + A.LEAF_UPDATE_COUNT + A.LEAF_DELETE_COUNT desc

 

  • Tempdb 증가 원인 추적

USE TEMPDB;

 

-- TEMPDB allocated by session:

select *, (allocated_mb - deallocated_mb)reserved_mb from

(

select session_id

   ,(((sum(internal_objects_alloc_page_count + user_objects_alloc_page_count)*8024)/1024)/1024) as allocated_mb

   ,(((sum(internal_objects_dealloc_page_count + user_objects_dealloc_page_count)*8024)/1024)/1024) as deallocated_mb

from sys.dm_db_task_space_usage

group by session_id

) x where allocated_mb > 0;

 

-- TEMPDB allocated by object:

select o.type_desc

, substring(o.name,1,charindex('__',o.name)+1)+right(o.name,12) table_shortname

, si.name index_name

, case si.index_id when 0 then 'HEAP' when 1 then 'CLUSTERED' else 'NONCLUSTERED' end index_type

, row_count

, ((reserved_page_count * 8024) / 1024 / 1024)reserved_mb

, create_date

from sys.dm_db_partition_stats ps

left join sys.objects o on ps.object_id = o.object_id

left join sys.indexes si on si.object_id = o.object_id and si.index_id = ps.index_id

where is_ms_shipped = 0

order by reserved_page_count desc;

 

-- TEMPDB Data/Log File Auto Growth events:

DECLARE @filename VARCHAR(500)

SELECT @filename = SUBSTRING(path, 0,LEN(path) - CHARINDEX('\',REVERSE(path)) + 1)+ '\Log.trc'

   FROM sys.traces

      WHERE is_default = 1 ;

SELECT TOP 100

  te.Name AS EventName

  ,StartTime

  ,NTDomainName

  ,NTUserName

  ,LoginName

  ,ApplicationName

  ,HostName

  ,DatabaseName

  ,Filename

  ,IntegerData/128 [Size MB]

  ,CAST(Duration/1000000. AS DECIMAL(20,2)) AS [Duration sec]

  ,EndTime

  ,SPID

  ,SessionLoginName

  ,Error

  ,Success

  ,IsSystem

FROM fn_trace_gettable(@fileName, DEFAULT) gt

  INNER JOIN sys.trace_events te ON EventClass = te.trace_event_id

WHERE EventClass IN(92, 93) -- Data/Log File Auto Grow

AND DatabaseName = 'tempdb'

ORDER BY StartTime DESC;

 

  • Tempdb 대한 추적 플래그 T1118 을 설정 합니다.
  • DBCC traceon(1118, -1)

 


+ Recent posts