1. 监控MSSQL语句执行情况的重要性
在开发和运维过程中,监控MSSQL数据库是至关重要的。通过监控语句执行情况,我们可以了解数据库性能瓶颈所在,及时发现潜在问题并进行优化。此外,还可以预测未来的容量需求,为系统规划和部署提供依据。
下面,介绍一些监控MSSQL语句执行情况的最佳实践。
2. 开启性能计数器
2.1 理解性能计数器
性能计数器是一种微软Windows工具,用于跟踪操作系统、应用程序和硬件设备的性能数据。对于MSSQL服务器的系统管理员来说,性能计数器是监控性能的重要工具之一。
2.2 如何开启性能计数器
开启性能计数器的过程非常简单:
-- 开启性能计数器
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'recovery interval', 10;
RECONFIGURE;
通过上述步骤,我们可以在SQL Server Management Studio(SSMS)的“性能监视器”选项卡上,监控各种性能指标,包括CPU利用率、内存利用率、磁盘I/O使用率等。
3. 监控长时间运行的语句
长时间运行的SQL语句可能会导致服务器性能下降,甚至是系统崩溃。可以通过以下步骤来监控长时间运行的SQL语句:
3.1 使用系统监视器跟踪事件
系统监视器是一个强大的性能监视工具,可以帮助我们找到数据库性能问题的根源。以下是使用系统监视器跟踪长时间运行的语句的步骤:
在SSMS中,选择“工具”->“SQL Server Profiler”。
选择“新建跟踪”。
选择“T-SQL”事件,然后选择“RPC Completed”和“SQL: BatchCompleted”事件。
在“过滤器”选项卡上,设置“Duration”大于10秒。
通过上述步骤,我们可以在跟踪文件中找到长时间运行的SQL语句。可以通过分析这些语句,找到慢查询的原因,并进行优化。
3.2 使用DMV监控长时间运行的查询
动态管理视图(DMV)可以帮助我们监控数据库实例和资源的使用情况。以下是使用DMV监控长时间运行的语句的步骤:
打开SQL Server管理器。
扩展Database Engine节点。
右键单击“动态管理视图”。
选择“新建查询”。
在新的查询视图中,输入以下查询语句:
SELECT TOP 10
t.TEXT QueryName,
s.execution_count AS ExecutionCount,
s.total_elapsed_time AS TotalElapsedTime,
s.total_worker_time AS TotalWorkerTime,
s.total_logical_reads AS TotalLogicalReads,
s.creation_time AS CreationTime,
s.last_execution_time AS LastExecutionTime,
CAST((s.total_elapsed_time / s.execution_count) / 1000 AS decimal(18,2)) as AverageElapsedSeconds,
CAST(s.total_worker_time / s.execution_count / 1000 AS decimal(18,2)) as AverageWorkerSeconds,
CAST(s.total_logical_reads / s.execution_count AS decimal(18,2)) as AverageLogicalReads
FROM sys.dm_exec_query_stats s
CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) t
WHERE s.last_execution_time > DATEADD(minute, -10, GETDATE())
ORDER BY AverageElapsedSeconds DESC;
通过上述查询语句,我们可以查看最近10分钟内运行时间最长的查询,并分析它们的执行计划,找到慢查询的瓶颈。
4. 监控锁和死锁问题
锁和死锁问题也是数据库管理员必须关注的问题。以下是监控锁和死锁问题的最佳实践:
4.1 使用系统视图监控锁问题
可以使用下列查询语句监视锁和阻塞问题:
SELECT
l.request_session_id AS SPID,
r.command AS CommandType,
DB_NAME(l.resource_database_id) AS DatabaseName,
CASE l.resource_type
WHEN 'OBJECT' THEN OBJECT_NAME(l.resource_associated_entity_id)
WHEN 'DATABASE' THEN DB_NAME(l.resource_database_id)
WHEN 'FILE' THEN
(
SELECT name
FROM sys.database_files
WHERE file_id = l.resource_associated_entity_id AND database_id = l.resource_database_id
)
WHEN 'PAGE' THEN FORMAT(l.resource_associated_entity_id, 'x')
ELSE ''
END AS EntityName,
CASE l.resource_type
WHEN 'OBJECT' THEN 'OBJECT'
WHEN 'DATABASE' THEN 'DATABASE'
WHEN 'FILE' THEN 'FILE'
WHEN 'PAGE' THEN 'PAGE'
WHEN 'KEY' THEN 'INDEX'
WHEN 'RID' THEN 'ROW'
ELSE l.resource_type
END AS LockType,
r.status AS RequestStatus,
r.wait_type AS WaitType,
r.last_wait_type AS LastWaitType,
r.wait_time AS WaitTime_ms,
r.blocking_session_id AS BlockingSPID,
l.resource_description AS LockDescription,
r.cpu_time AS CPU_Time_ms,
r.total_elapsed_time AS ElapsedTime_ms,
r.reads AS LogicalReads,
r.writes AS Writes,
r.row_count AS RowsRead,
r.granted_query_memory AS GrantedQueryMemory
FROM sys.dm_tran_locks AS l
INNER JOIN sys.dm_exec_requests AS r ON l.request_session_id = r.session_id
WHERE l.resource_type IN ('DATABASE', 'FILE', 'OBJECT', 'PAGE')
ORDER BY r.total_elapsed_time DESC;
通过上述查询,可以了解到哪些会话正在请求或持有需要锁定的数据库对象,并对必要时进行解锁。
4.2 使用Extended Events监控死锁问题
死锁是指两个或多个会话之间的互相等待,并且无法继续执行的情况。Extended Events是一种SQL Server自带的轻量级事件跟踪系统,可以用于监视死锁。
以下是使用Extended Events监控死锁的步骤:
在SSMS中,选择“新建查询”。
输入以下查询语句:
IF OBJECT_ID('tempdb..#DeadlockSessionList') IS NOT NULL DROP TABLE #DeadlockSessionList;
CREATE TABLE #DeadlockSessionList (DeadlockID INT PRIMARY KEY);
GO
DECLARE @xml XML;
SET @xml = (SELECT CAST(target_data as XML) as target_data
FROM sys.dm_xe_session_targets as t
JOIN sys.dm_xe_sessions as s on t.event_session_address = s.address
WHERE t.target_name = 'ring_buffer')
DECLARE @blk TABLE (blk XML);
INSERT INTO @blk EXEC sys.fn_xe_telemetry_blob (@xml);
WITH FindDeadlocks AS
(
-- Use the XML parser to extract deadlock graph
SELECT
x.Deadlock.value('@id', 'varchar(100)') AS DeadlockID
FROM
@blk AS B
CROSS APPLY B.blk.nodes('//RingBufferTarget/event[(@name=''xml_deadlock_report'') and data[@name="duration"]/value > 0]') x(Deadlock)
)
INSERT INTO #DeadlockSessionList (DeadlockID)
SELECT DISTINCT DeadlockID FROM FindDeadlocks;
SELECT
DeadlockId = ISNULL(ln.value('(data/value)[1]','varchar(50)'),'N/A'),
DeadlockOwner = ISNULL(ln.value('(data/value)[4]','varchar(100)'),'N/A'),
WaiterType = ISNULL(ln.value('(data/value)[6]/child::*[1]','varchar(100)'),'N/A'),
WaiterObject = ISNULL(ln.value('(data/value)[8]','varchar(100)'),'N/A'),
BlockerType = ISNULL(ln.value('(data/value)[10]/child::*[1]','varchar(100)'),'N/A'),
BlockerObject = ISNULL(ln.value('(data/value)[12]','varchar(100)'),'N/A'),
DeadlockTime = CAST(RIGHT(ln.value('(data/@timestamp)[1]'),'24') AS DATETIMEOFFSET),
ResourceList = CAST(ln.query('./data[@name="resource-list"]') AS XML),
DeadlockList = ln.query('.'),
xact_sequence_value = ISNULL(ln.query('./data[@name="transaction-list"]/child::*/@XactSeq')[1],'N/A')
FROM
sys.dm_xe_session_targets st
INNER JOIN sys.dm_xe_sessions s ON (s.address = st.event_session_address)
OUTER APPLY sys.fn_xe_file_target_read_file(st.target_name, NULL, NULL, NULL) f
OUTER APPLY f.file_content.nodes ('//RingBufferTarget/event') eye(ln)
WHERE DeadlockID IN(SELECT DeadlockID FROM #DeadlockSessionList);
通过上述查询,我们可以查看死锁事件的详细信息,了解死锁的原因,并解除死锁。
5. 总结
监控MSSQL语句执行情况对于优化数据库性能和提高系统稳定性至关重要。本文介绍了一些监控MSSQL语句执行情况的最佳实践,包括开启性能计数器、监控长时间运行的语句、监控锁和死锁问题等。通过这些最佳实践,我们可以更好地了解数据库性能瓶颈所在,并及时发现和解决潜在问题,提高数据库的可用性和稳定性。