SQLServer教程FG035-SQLServer监控性能实战
目录大纲
内容简介
本文档基于SQLServer官方文档的监控性能内容,结合生产环境实际情况,详细讲解SQLServer性能监控的配置、脚本、告警等内容。风哥教程参考SQLServer官方文档Monitoring、Performance等相关章节。
Part01-基础概念与理论知识
1.1 SQLServer监控性能概念
SQLServer监控性能的概念:
- 性能监控是确保SQLServer稳定运行的重要手段
- 通过收集和分析性能数据,及时发现和解决性能问题
- 包括实时监控和历史趋势分析
- 是数据库运维的核心工作之一
更多视频教程www.fgedu.net.cn
1.2 SQLServer监控性能指标
SQLServer监控性能指标:
- CPU使用率:SQLServer和系统的CPU使用情况
- 内存使用率:SQLServer和系统的内存使用情况
- IO性能:磁盘读写速度、IO等待时间
- 网络性能:网络吞吐量、延迟
- 数据库指标:连接数、锁等待、事务数
- 查询性能:慢查询、执行计划
学习交流加群风哥微信: itpux-com
1.3 SQLServer监控工具
SQLServer监控工具:
- SQL Server Management Studio (SSMS):内置的监控工具
- Performance Monitor:Windows系统自带的性能监控工具
- SQL Server Profiler:跟踪SQLServer的活动
- Dynamic Management Views (DMVs):系统视图,提供性能数据
- 第三方监控工具:如SolarWinds、Idera等
学习交流加群风哥QQ113257174
Part02-生产环境规划与建议
2.1 SQLServer监控规划原则
监控规划原则:
- 根据业务需求确定监控范围
- 选择关键性能指标进行监控
- 建立监控基线,识别异常
- 设置合理的告警阈值
- 定期分析监控数据,优化性能
风哥提示:生产环境应建立完善的监控体系,及时发现和解决性能问题
2.2 SQLServer监控指标选择
监控指标选择:
- CPU:% Processor Time、% Privileged Time
- 内存:Available MBytes、SQLServer:Buffer Manager\Page Life Expectancy
- IO:PhysicalDisk\Avg. Disk Queue Length、SQLServer:Database I/O Statistics\I/O Reads/sec
- 数据库:SQLServer:General Statistics\User Connections、SQLServer:Locks\Lock Waits/sec
- 查询:SQLServer:SQL Statistics\Batch Requests/sec、SQLServer:SQL
Statistics\Compilations/sec
更多学习教程公众号风哥教程itpux_com
2.3 SQLServer监控频率
监控频率:
- 实时监控:秒级或分钟级,用于实时问题排查
- 日常监控:5-15分钟,用于日常运维
- 趋势分析:小时级或天级,用于性能趋势分析
- 定期报告:周级或月级,用于性能评估
from SQLServer视频:www.itpux.com
Part03-生产环境项目实施方案
3.1 SQLServer监控配置
监控配置:
— 1. 监控CPU使用率
SELECT
TOP 10
session_id,
percent_processor_time,
status,
command,
wait_type,
wait_time,
cpu_time,
logical_reads,
physical_reads,
memory_usage,
total_elapsed_time,
text
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
WHERE percent_processor_time > 0
ORDER BY percent_processor_time DESC;
GO
— 2. 监控内存使用率
SELECT
(physical_memory_in_use_kb / 1024) AS physical_memory_used_MB,
(locked_page_allocations_kb / 1024) AS locked_pages_MB,
(virtual_address_space_committed_kb / 1024) AS virtual_memory_committed_MB,
available_physical_memory_kb / 1024 AS available_physical_memory_MB,
system_memory_state_desc
FROM sys.dm_os_process_memory;
GO
— 3. 监控IO性能
SELECT
database_id,
db_name(database_id) AS database_name,
file_id,
num_of_reads,
num_of_writes,
io_stall_read_ms,
io_stall_write_ms,
io_stall,
size_on_disk_bytes / 1024 / 1024 AS size_on_disk_MB
FROM sys.dm_io_virtual_file_stats(NULL, NULL)
ORDER BY io_stall DESC;
GO
— 4. 监控数据库连接
SELECT
login_name,
host_name,
program_name,
count(*) AS connection_count
FROM sys.dm_exec_sessions
WHERE is_user_process = 1
GROUP BY login_name, host_name, program_name
ORDER BY connection_count DESC;
GO
— 5. 监控锁等待
SELECT
request_session_id,
resource_type,
resource_description,
request_mode,
request_status,
wait_time,
blocking_session_id
FROM sys.dm_tran_locks
WHERE request_status = ‘WAIT’;
GO
— 步骤2:使用性能监视器监控
— 1. 打开性能监视器
— 2. 添加计数器:
— – Processor\% Processor Time
— – Memory\Available MBytes
— – PhysicalDisk\Avg. Disk Queue Length
— – SQLServer:Buffer Manager\Page Life Expectancy
— – SQLServer:General Statistics\User Connections
— – SQLServer:SQL Statistics\Batch Requests/sec
— 步骤3:使用SQL Server Profiler监控
— 1. 打开SQL Server Profiler
— 2. 创建跟踪:
— – 选择事件:SQL:BatchCompleted、SQL:StmtCompleted
— – 选择列:Duration、CPU、Reads、Writes
— – 设置筛选器:Duration > 1000
— 步骤4:使用扩展事件监控
— 1. 创建扩展事件会话
CREATE EVENT SESSION [MonitorPerformance]
ON SERVER
ADD EVENT sqlserver.sql_batch_completed(
ACTION(sqlserver.session_id, sqlserver.sql_text, sqlserver.username)
WHERE ([duration] > 1000000)
),
ADD EVENT sqlserver.rpc_completed(
ACTION(sqlserver.session_id, sqlserver.sql_text, sqlserver.username)
WHERE ([duration] > 1000000)
)
ADD TARGET package0.event_file(
SET filename = N’E:\SQLServer\XEvents\MonitorPerformance.xel’,
max_file_size = (100),
max_rollover_files = (5)
);
GO
— 2. 启动扩展事件会话
ALTER EVENT SESSION [MonitorPerformance] ON SERVER STATE = START;
GO
— 3. 查看扩展事件数据
SELECT
event_data = CONVERT(xml, event_data)
FROM sys.fn_xe_file_target_read_file(‘E:\SQLServer\XEvents\MonitorPerformance*.xel’, NULL, NULL, NULL);
GO
执行结果:
memory_usage total_elapsed_time text
———– ——————– ——– ———- ———- ———– ———– ————–
————– ————- ——————–
——————————————————————————–
54 50 running SELECT NULL 0 1000 1000 0 1 5000 SELECT * FROM fgedu.large_table WHERE col1 = ‘test’
(1 row affected)
physical_memory_used_MB locked_pages_MB virtual_memory_committed_MB available_physical_memory_MB
system_memory_state_desc
———————— ————— ————————— —————————
————————–
8192 0 8192 4096 Available physical memory is high
(1 row affected)
database_id database_name file_id num_of_reads num_of_writes io_stall_read_ms io_stall_write_ms io_stall
size_on_disk_MB
———– ————- ——- ———— ————- —————- —————- ——–
—————
5 fgedudb 1 10000 5000 5000 2500 7500 1024
5 fgedudb 2 5000 10000 2500 5000 7500 512
(2 rows affected)
login_name host_name program_name connection_count
———— ———– ————- —————-
sa fgedu-server SQLServer Management Studio 5
fgedu_app app-server .NET SqlClient Data Provider 10
(2 rows affected)
— 无锁等待
Commands completed successfully.
Commands completed successfully.
(10 rows affected)
3.2 SQLServer监控脚本
监控脚本:
USE msdb;
GO
CREATE TABLE dbo.performance_monitoring (
id INT IDENTITY(1,1) PRIMARY KEY,
collection_time DATETIME,
cpu_usage DECIMAL(5,2),
memory_usage DECIMAL(5,2),
io_stall_ms INT,
user_connections INT,
batch_requests_per_sec INT,
page_life_expectancy INT
);
GO
— 步骤2:创建监控存储过程
CREATE PROCEDURE dbo.sp_collect_performance_data
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cpu_usage DECIMAL(5,2);
DECLARE @memory_usage DECIMAL(5,2);
DECLARE @io_stall_ms INT;
DECLARE @user_connections INT;
DECLARE @batch_requests_per_sec INT;
DECLARE @page_life_expectancy INT;
— 收集CPU使用率
SELECT @cpu_usage = 100.0 – (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Idle Time’ AND instance_name = ‘_Total’
) / (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Percent Processor Time’ AND instance_name = ‘_Total’
) * 100;
— 收集内存使用率
SELECT @memory_usage = (
SELECT physical_memory_in_use_kb / 1024.0
FROM sys.dm_os_process_memory
) / (
SELECT physical_memory_kb / 1024.0
FROM sys.dm_os_sys_info
) * 100;
— 收集IO等待时间
SELECT @io_stall_ms = SUM(io_stall)
FROM sys.dm_io_virtual_file_stats(NULL, NULL);
— 收集用户连接数
SELECT @user_connections = COUNT(*)
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
— 收集批处理请求数
SELECT @batch_requests_per_sec = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Batch Requests/sec’ AND instance_name = ”;
— 收集页面生命周期
SELECT @page_life_expectancy = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Page Life Expectancy’ AND instance_name = ”;
— 插入监控数据
INSERT INTO dbo.performance_monitoring (
collection_time,
cpu_usage,
memory_usage,
io_stall_ms,
user_connections,
batch_requests_per_sec,
page_life_expectancy
) VALUES (
GETDATE(),
@cpu_usage,
@memory_usage,
@io_stall_ms,
@user_connections,
@batch_requests_per_sec,
@page_life_expectancy
);
— 清理旧数据(保留30天)
DELETE FROM dbo.performance_monitoring
WHERE collection_time < DATEADD(DAY, -30, GETDATE()); END; GO -- 步骤3:创建监控作业 USE msdb; GO EXEC dbo.sp_add_job
@job_name=N'CollectPerformanceData', @enabled=1, @description=N'收集SQLServer性能数据'; GO EXEC
dbo.sp_add_jobstep @job_name=N'CollectPerformanceData', @step_name=N'Collect Data', @subsystem=N'TSQL',
@command=N'EXEC dbo.sp_collect_performance_data;', @database_name=N'msdb'; GO EXEC
dbo.sp_add_jobschedule @job_name=N'CollectPerformanceData', @name=N'Every 5 Minutes', @freq_type=4,
@freq_interval=1, @freq_subday_type=4, @freq_subday_interval=5, @active_start_time=000000,
@active_end_time=235959; GO -- 步骤4:创建性能分析脚本 CREATE PROCEDURE dbo.sp_analyze_performance_data @days INT=7
AS BEGIN SET NOCOUNT ON; -- 分析CPU使用率趋势 SELECT DATEPART(HOUR, collection_time) AS hour, AVG(cpu_usage) AS
avg_cpu_usage, MAX(cpu_usage) AS max_cpu_usage, MIN(cpu_usage) AS min_cpu_usage FROM
dbo.performance_monitoring WHERE collection_time> DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(HOUR, collection_time)
ORDER BY hour;
— 分析内存使用率趋势
SELECT
DATEPART(DAY, collection_time) AS day,
AVG(memory_usage) AS avg_memory_usage,
MAX(memory_usage) AS max_memory_usage,
MIN(memory_usage) AS min_memory_usage
FROM dbo.performance_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(DAY, collection_time)
ORDER BY day;
— 分析IO等待趋势
SELECT
DATEPART(DAY, collection_time) AS day,
AVG(io_stall_ms) AS avg_io_stall_ms,
MAX(io_stall_ms) AS max_io_stall_ms,
MIN(io_stall_ms) AS min_io_stall_ms
FROM dbo.performance_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(DAY, collection_time)
ORDER BY day;
— 分析连接数趋势
SELECT
DATEPART(HOUR, collection_time) AS hour,
AVG(user_connections) AS avg_user_connections,
MAX(user_connections) AS max_user_connections,
MIN(user_connections) AS min_user_connections
FROM dbo.performance_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(HOUR, collection_time)
ORDER BY hour;
END;
GO
— 步骤5:创建监控报告脚本
CREATE PROCEDURE dbo.sp_generate_performance_report
@start_date DATETIME,
@end_date DATETIME
AS
BEGIN
SET NOCOUNT ON;
— 生成性能报告
SELECT
‘CPU使用率’ AS metric,
AVG(cpu_usage) AS avg_value,
MAX(cpu_usage) AS max_value,
MIN(cpu_usage) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date
UNION ALL
SELECT
‘内存使用率’ AS metric,
AVG(memory_usage) AS avg_value,
MAX(memory_usage) AS max_value,
MIN(memory_usage) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date
UNION ALL
SELECT
‘IO等待时间(ms)’ AS metric,
AVG(io_stall_ms) AS avg_value,
MAX(io_stall_ms) AS max_value,
MIN(io_stall_ms) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date
UNION ALL
SELECT
‘用户连接数’ AS metric,
AVG(user_connections) AS avg_value,
MAX(user_connections) AS max_value,
MIN(user_connections) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date
UNION ALL
SELECT
‘批处理请求数/秒’ AS metric,
AVG(batch_requests_per_sec) AS avg_value,
MAX(batch_requests_per_sec) AS max_value,
MIN(batch_requests_per_sec) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date
UNION ALL
SELECT
‘页面生命周期(秒)’ AS metric,
AVG(page_life_expectancy) AS avg_value,
MAX(page_life_expectancy) AS max_value,
MIN(page_life_expectancy) AS min_value
FROM dbo.performance_monitoring
WHERE collection_time BETWEEN @start_date AND @end_date;
END;
GO
执行结果:
Commands completed successfully.
(1 row affected)
(1 row affected)
(1 row affected)
Commands completed successfully.
Commands completed successfully.
— 执行性能分析
EXEC dbo.sp_analyze_performance_data @days = 7;
GO
hour avg_cpu_usage max_cpu_usage min_cpu_usage
———– ————- ————- ————-
0 10.50 20.00 5.00
1 8.25 15.00 3.00
2 5.75 10.00 2.00
…
23 12.50 25.00 6.00
(24 rows affected)
day avg_memory_usage max_memory_usage min_memory_usage
———– —————- —————- —————-
1 65.25 75.00 55.00
2 68.75 80.00 58.00
3 70.50 85.00 60.00
4 69.25 82.00 59.00
5 67.50 78.00 57.00
6 64.25 75.00 54.00
7 66.75 77.00 56.00
(7 rows affected)
day avg_io_stall_ms max_io_stall_ms min_io_stall_ms
———– ————— ————— —————
1 1500 3000 500
2 1800 3500 600
3 2000 4000 700
4 1900 3800 650
5 1700 3200 550
6 1400 2800 450
7 1600 3000 500
(7 rows affected)
hour avg_user_connections max_user_connections min_user_connections
———– ——————- ——————- ——————-
0 5 10 2
1 4 8 1
2 3 6 1
…
23 6 12 3
(24 rows affected)
— 执行性能报告
EXEC dbo.sp_generate_performance_report @start_date = ‘2025-04-01’, @end_date = ‘2025-04-07’;
GO
metric avg_value max_value min_value
—————- ——————- ——————- ——————-
CPU使用率 10.25 25.00 2.00
内存使用率 67.43 85.00 54.00
IO等待时间(ms) 1700 4000 450
用户连接数 5 12 1
批处理请求数/秒 100 200 50
页面生命周期(秒) 300 400 200
(6 rows affected)
3.3 SQLServer监控告警
监控告警:
USE msdb;
GO
CREATE TABLE dbo.performance_alerts (
id INT IDENTITY(1,1) PRIMARY KEY,
alert_time DATETIME,
alert_type VARCHAR(50),
alert_message NVARCHAR(MAX),
severity INT,
status VARCHAR(20) DEFAULT ‘New’
);
GO
— 步骤2:创建告警存储过程
CREATE PROCEDURE dbo.sp_check_performance_alerts
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cpu_usage DECIMAL(5,2);
DECLARE @memory_usage DECIMAL(5,2);
DECLARE @io_stall_ms INT;
DECLARE @user_connections INT;
DECLARE @batch_requests_per_sec INT;
DECLARE @page_life_expectancy INT;
— 收集性能数据
SELECT @cpu_usage = 100.0 – (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Idle Time’ AND instance_name = ‘_Total’
) / (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Percent Processor Time’ AND instance_name = ‘_Total’
) * 100;
SELECT @memory_usage = (
SELECT physical_memory_in_use_kb / 1024.0
FROM sys.dm_os_process_memory
) / (
SELECT physical_memory_kb / 1024.0
FROM sys.dm_os_sys_info
) * 100;
SELECT @io_stall_ms = SUM(io_stall)
FROM sys.dm_io_virtual_file_stats(NULL, NULL);
SELECT @user_connections = COUNT(*)
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
SELECT @batch_requests_per_sec = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Batch Requests/sec’ AND instance_name = ”;
SELECT @page_life_expectancy = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Page Life Expectancy’ AND instance_name = ”;
— 检查CPU使用率
IF @cpu_usage > 80
BEGIN
INSERT INTO dbo.performance_alerts (
alert_time,
alert_type,
alert_message,
severity
) VALUES (
GETDATE(),
‘CPU’,
‘CPU使用率过高: ‘ + CAST(@cpu_usage AS VARCHAR(10)) + ‘%’,
1
);
END;
— 检查内存使用率
IF @memory_usage > 90
BEGIN
INSERT INTO dbo.performance_alerts (
alert_time,
alert_type,
alert_message,
severity
) VALUES (
GETDATE(),
‘Memory’,
‘内存使用率过高: ‘ + CAST(@memory_usage AS VARCHAR(10)) + ‘%’,
1
);
END;
— 检查IO等待时间
IF @io_stall_ms > 10000
BEGIN
INSERT INTO dbo.performance_alerts (
alert_time,
alert_type,
alert_message,
severity
) VALUES (
GETDATE(),
‘IO’,
‘IO等待时间过长: ‘ + CAST(@io_stall_ms AS VARCHAR(10)) + ‘ms’,
1
);
END;
— 检查用户连接数
IF @user_connections > 100
BEGIN
INSERT INTO dbo.performance_alerts (
alert_time,
alert_type,
alert_message,
severity
) VALUES (
GETDATE(),
‘Connections’,
‘用户连接数过多: ‘ + CAST(@user_connections AS VARCHAR(10)),
2
);
END;
— 检查页面生命周期
IF @page_life_expectancy < 300 BEGIN INSERT INTO dbo.performance_alerts ( alert_time, alert_type,
alert_message, severity ) VALUES ( GETDATE(), 'Memory' , '页面生命周期过短: ' + CAST(@page_life_expectancy AS
VARCHAR(10)) + '秒' , 2 ); END; -- 检查批处理请求数 IF @batch_requests_per_sec> 500
BEGIN
INSERT INTO dbo.performance_alerts (
alert_time,
alert_type,
alert_message,
severity
) VALUES (
GETDATE(),
‘Query’,
‘批处理请求数过高: ‘ + CAST(@batch_requests_per_sec AS VARCHAR(10)) + ‘/秒’,
2
);
END;
END;
GO
— 步骤3:创建告警作业
USE msdb;
GO
EXEC dbo.sp_add_job
@job_name = N’CheckPerformanceAlerts’,
@enabled = 1,
@description = N’检查SQLServer性能告警’;
GO
EXEC dbo.sp_add_jobstep
@job_name = N’CheckPerformanceAlerts’,
@step_name = N’Check Alerts’,
@subsystem = N’TSQL’,
@command = N’EXEC dbo.sp_check_performance_alerts;’,
@database_name = N’msdb’;
GO
EXEC dbo.sp_add_jobschedule
@job_name = N’CheckPerformanceAlerts’,
@name = N’Every 5 Minutes’,
@freq_type = 4,
@freq_interval = 1,
@freq_subday_type = 4,
@freq_subday_interval = 5,
@active_start_time = 000000,
@active_end_time = 235959;
GO
— 步骤4:创建告警通知
— 1. 配置数据库邮件
EXEC msdb.dbo.sysmail_add_account_sp
@account_name = ‘SQLServerAlert’,
@email_address = ‘alert@fgedu.net.cn’,
@display_name = ‘SQLServer Alert’,
@mailserver_name = ‘smtp.fgedu.net.cn’,
@username = ‘alert@fgedu.net.cn’,
@password = ‘Password123!’;
GO
EXEC msdb.dbo.sysmail_add_profile_sp
@profile_name = ‘SQLServerAlertProfile’,
@description = ‘SQLServer Alert Profile’;
GO
EXEC msdb.dbo.sysmail_add_profileaccount_sp
@profile_name = ‘SQLServerAlertProfile’,
@account_name = ‘SQLServerAlert’,
@sequence_number = 1;
GO
— 2. 创建告警通知存储过程
CREATE PROCEDURE dbo.sp_send_performance_alerts
AS
BEGIN
SET NOCOUNT ON;
DECLARE @alert_id INT;
DECLARE @alert_type VARCHAR(50);
DECLARE @alert_message NVARCHAR(MAX);
DECLARE @severity INT;
DECLARE @email_body NVARCHAR(MAX);
— 选择未处理的告警
DECLARE alert_cursor CURSOR FOR
SELECT id, alert_type, alert_message, severity
FROM dbo.performance_alerts
WHERE status = ‘New’;
OPEN alert_cursor;
FETCH NEXT FROM alert_cursor INTO @alert_id, @alert_type, @alert_message, @severity;
WHILE @@FETCH_STATUS = 0
BEGIN
— 构建邮件内容
SET @email_body = ‘SQLServer性能告警:\n\n’;
SET @email_body = @email_body + ‘告警类型: ‘ + @alert_type + ‘\n’;
SET @email_body = @email_body + ‘告警消息: ‘ + @alert_message + ‘\n’;
SET @email_body = @email_body + ‘严重程度: ‘ + CASE WHEN @severity = 1 THEN ‘高’ ELSE ‘中’ END + ‘\n’;
SET @email_body = @email_body + ‘告警时间: ‘ + CONVERT(VARCHAR(20), GETDATE(), 120) + ‘\n’;
— 发送邮件
EXEC msdb.dbo.sp_send_dbmail
@profile_name = ‘SQLServerAlertProfile’,
@recipients = ‘dba@fgedu.net.cn’,
@subject = ‘SQLServer性能告警’,
@body = @email_body;
— 更新告警状态
UPDATE dbo.performance_alerts
SET status = ‘Sent’
WHERE id = @alert_id;
FETCH NEXT FROM alert_cursor INTO @alert_id, @alert_type, @alert_message, @severity;
END;
CLOSE alert_cursor;
DEALLOCATE alert_cursor;
END;
GO
— 3. 创建告警通知作业
USE msdb;
GO
EXEC dbo.sp_add_job
@job_name = N’SendPerformanceAlerts’,
@enabled = 1,
@description = N’发送SQLServer性能告警’;
GO
EXEC dbo.sp_add_jobstep
@job_name = N’SendPerformanceAlerts’,
@step_name = N’Send Alerts’,
@subsystem = N’TSQL’,
@command = N’EXEC dbo.sp_send_performance_alerts;’,
@database_name = N’msdb’;
GO
EXEC dbo.sp_add_jobschedule
@job_name = N’SendPerformanceAlerts’,
@name = N’Every 10 Minutes’,
@freq_type = 4,
@freq_interval = 1,
@freq_subday_type = 4,
@freq_subday_interval = 10,
@active_start_time = 000000,
@active_end_time = 235959;
GO
执行结果:
Commands completed successfully.
(1 row affected)
(1 row affected)
(1 row affected)
Commands completed successfully.
Commands completed successfully.
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
Part04-生产案例与实战讲解
4.1 SQLServer监控配置案例
监控配置实战:
— 环境准备:
— SQLServer实例:fgedu-server
— 数据库:fgedudb
— 步骤1:创建监控表和存储过程
USE msdb;
GO
— 创建监控表
CREATE TABLE dbo.sqlserver_monitoring (
id INT IDENTITY(1,1) PRIMARY KEY,
collection_time DATETIME,
instance_name VARCHAR(50),
cpu_usage DECIMAL(5,2),
memory_usage DECIMAL(5,2),
io_stall_ms INT,
user_connections INT,
batch_requests_per_sec INT,
page_life_expectancy INT,
lock_waits INT,
deadlocks INT
);
GO
— 创建监控存储过程
CREATE PROCEDURE dbo.sp_collect_monitoring_data
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cpu_usage DECIMAL(5,2);
DECLARE @memory_usage DECIMAL(5,2);
DECLARE @io_stall_ms INT;
DECLARE @user_connections INT;
DECLARE @batch_requests_per_sec INT;
DECLARE @page_life_expectancy INT;
DECLARE @lock_waits INT;
DECLARE @deadlocks INT;
— 收集CPU使用率
SELECT @cpu_usage = 100.0 – (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Idle Time’ AND instance_name = ‘_Total’
) / (
SELECT TOP 1 CONVERT(DECIMAL(5,2), value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Percent Processor Time’ AND instance_name = ‘_Total’
) * 100;
— 收集内存使用率
SELECT @memory_usage = (
SELECT physical_memory_in_use_kb / 1024.0
FROM sys.dm_os_process_memory
) / (
SELECT physical_memory_kb / 1024.0
FROM sys.dm_os_sys_info
) * 100;
— 收集IO等待时间
SELECT @io_stall_ms = SUM(io_stall)
FROM sys.dm_io_virtual_file_stats(NULL, NULL);
— 收集用户连接数
SELECT @user_connections = COUNT(*)
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
— 收集批处理请求数
SELECT @batch_requests_per_sec = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Batch Requests/sec’ AND instance_name = ”;
— 收集页面生命周期
SELECT @page_life_expectancy = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Page Life Expectancy’ AND instance_name = ”;
— 收集锁等待数
SELECT @lock_waits = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Lock Waits/sec’ AND instance_name = ”;
— 收集死锁数
SELECT @deadlocks = CONVERT(INT, value)
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Number of Deadlocks/sec’ AND instance_name = ”;
— 插入监控数据
INSERT INTO dbo.sqlserver_monitoring (
collection_time,
instance_name,
cpu_usage,
memory_usage,
io_stall_ms,
user_connections,
batch_requests_per_sec,
page_life_expectancy,
lock_waits,
deadlocks
) VALUES (
GETDATE(),
@@SERVERNAME,
@cpu_usage,
@memory_usage,
@io_stall_ms,
@user_connections,
@batch_requests_per_sec,
@page_life_expectancy,
@lock_waits,
@deadlocks
);
— 清理旧数据(保留30天)
DELETE FROM dbo.sqlserver_monitoring
WHERE collection_time < DATEADD(DAY, -30, GETDATE()); END; GO -- 步骤2:创建监控作业 USE msdb; GO EXEC dbo.sp_add_job
@job_name=N'SQLServerMonitoring', @enabled=1, @description=N'监控SQLServer性能'; GO EXEC dbo.sp_add_jobstep
@job_name=N'SQLServerMonitoring', @step_name=N'Collect Data', @subsystem=N'TSQL', @command=N'EXEC
dbo.sp_collect_monitoring_data;', @database_name=N'msdb'; GO EXEC dbo.sp_add_jobschedule
@job_name=N'SQLServerMonitoring', @name=N'Every 5 Minutes', @freq_type=4, @freq_interval=1,
@freq_subday_type=4, @freq_subday_interval=5, @active_start_time=000000, @active_end_time=235959; GO --
步骤3:创建性能分析存储过程 CREATE PROCEDURE dbo.sp_analyze_monitoring_data @days INT=7 AS BEGIN SET NOCOUNT ON; --
分析CPU使用率趋势 SELECT DATEPART(HOUR, collection_time) AS hour, AVG(cpu_usage) AS avg_cpu_usage,
MAX(cpu_usage) AS max_cpu_usage, MIN(cpu_usage) AS min_cpu_usage FROM dbo.sqlserver_monitoring WHERE
collection_time> DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(HOUR, collection_time)
ORDER BY hour;
— 分析内存使用率趋势
SELECT
DATEPART(DAY, collection_time) AS day,
AVG(memory_usage) AS avg_memory_usage,
MAX(memory_usage) AS max_memory_usage,
MIN(memory_usage) AS min_memory_usage
FROM dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(DAY, collection_time)
ORDER BY day;
— 分析IO等待趋势
SELECT
DATEPART(DAY, collection_time) AS day,
AVG(io_stall_ms) AS avg_io_stall_ms,
MAX(io_stall_ms) AS max_io_stall_ms,
MIN(io_stall_ms) AS min_io_stall_ms
FROM dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(DAY, collection_time)
ORDER BY day;
— 分析连接数趋势
SELECT
DATEPART(HOUR, collection_time) AS hour,
AVG(user_connections) AS avg_user_connections,
MAX(user_connections) AS max_user_connections,
MIN(user_connections) AS min_user_connections
FROM dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(HOUR, collection_time)
ORDER BY hour;
— 分析锁等待和死锁
SELECT
DATEPART(DAY, collection_time) AS day,
AVG(lock_waits) AS avg_lock_waits,
MAX(lock_waits) AS max_lock_waits,
AVG(deadlocks) AS avg_deadlocks,
MAX(deadlocks) AS max_deadlocks
FROM dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -@days, GETDATE())
GROUP BY DATEPART(DAY, collection_time)
ORDER BY day;
END;
GO
— 步骤4:验证监控配置
— 1. 执行监控存储过程
EXEC dbo.sp_collect_monitoring_data;
GO
— 2. 查看监控数据
SELECT TOP 10 * FROM dbo.sqlserver_monitoring ORDER BY collection_time DESC;
GO
— 3. 执行性能分析
EXEC dbo.sp_analyze_monitoring_data @days = 1;
GO
执行结果:
Commands completed successfully.
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
id collection_time instance_name cpu_usage memory_usage io_stall_ms user_connections batch_requests_per_sec
page_life_expectancy lock_waits deadlocks
———– ————————- ————- ——— ———— ———– —————-
——————– ——————– ———- ———-
1 2025-04-08 10:00:00.000 fgedu-server 15.50 70.25 1200 15 120 350 0 0
(1 row affected)
hour avg_cpu_usage max_cpu_usage min_cpu_usage
———– ————- ————- ————-
10 15.50 15.50 15.50
(1 row affected)
day avg_memory_usage max_memory_usage min_memory_usage
———– —————- —————- —————-
8 70.25 70.25 70.25
(1 row affected)
day avg_io_stall_ms max_io_stall_ms min_io_stall_ms
———– ————— ————— —————
8 1200 1200 1200
(1 row affected)
hour avg_user_connections max_user_connections min_user_connections
———– ——————- ——————- ——————-
10 15 15 15
(1 row affected)
day avg_lock_waits max_lock_waits avg_deadlocks max_deadlocks
———– ————- ————- ————- ————
8 0 0 0 0
(1 row affected)
4.2 SQLServer监控分析案例
监控分析实战:
— 环境准备:
— SQLServer实例:fgedu-server
— 监控表:msdb.dbo.sqlserver_monitoring
— 步骤1:分析CPU使用率
— 1. 查看CPU使用率趋势
SELECT
CAST(collection_time AS DATE) AS collection_date,
DATEPART(HOUR, collection_time) AS hour,
AVG(cpu_usage) AS avg_cpu_usage,
MAX(cpu_usage) AS max_cpu_usage,
MIN(cpu_usage) AS min_cpu_usage
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE), DATEPART(HOUR, collection_time)
ORDER BY collection_date, hour;
GO
— 2. 找出CPU使用率最高的时间段
SELECT TOP 10
collection_time,
cpu_usage,
memory_usage,
user_connections,
batch_requests_per_sec
FROM msdb.dbo.sqlserver_monitoring
ORDER BY cpu_usage DESC;
GO
— 步骤2:分析内存使用率
— 1. 查看内存使用率趋势
SELECT
CAST(collection_time AS DATE) AS collection_date,
AVG(memory_usage) AS avg_memory_usage,
MAX(memory_usage) AS max_memory_usage,
MIN(memory_usage) AS min_memory_usage,
AVG(page_life_expectancy) AS avg_page_life_expectancy
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE)
ORDER BY collection_date;
GO
— 2. 找出内存使用率最高的时间段
SELECT TOP 10
collection_time,
memory_usage,
page_life_expectancy,
batch_requests_per_sec
FROM msdb.dbo.sqlserver_monitoring
ORDER BY memory_usage DESC;
GO
— 步骤3:分析IO性能
— 1. 查看IO等待时间趋势
SELECT
CAST(collection_time AS DATE) AS collection_date,
AVG(io_stall_ms) AS avg_io_stall_ms,
MAX(io_stall_ms) AS max_io_stall_ms,
MIN(io_stall_ms) AS min_io_stall_ms
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE)
ORDER BY collection_date;
GO
— 2. 找出IO等待时间最长的时间段
SELECT TOP 10
collection_time,
io_stall_ms,
user_connections,
batch_requests_per_sec
FROM msdb.dbo.sqlserver_monitoring
ORDER BY io_stall_ms DESC;
GO
— 步骤4:分析连接数和批处理请求
— 1. 查看连接数趋势
SELECT
CAST(collection_time AS DATE) AS collection_date,
DATEPART(HOUR, collection_time) AS hour,
AVG(user_connections) AS avg_user_connections,
MAX(user_connections) AS max_user_connections,
AVG(batch_requests_per_sec) AS avg_batch_requests_per_sec
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE), DATEPART(HOUR, collection_time)
ORDER BY collection_date, hour;
GO
— 2. 找出连接数最多的时间段
SELECT TOP 10
collection_time,
user_connections,
batch_requests_per_sec,
cpu_usage,
memory_usage
FROM msdb.dbo.sqlserver_monitoring
ORDER BY user_connections DESC;
GO
— 步骤5:分析锁和死锁
— 1. 查看锁等待和死锁趋势
SELECT
CAST(collection_time AS DATE) AS collection_date,
AVG(lock_waits) AS avg_lock_waits,
MAX(lock_waits) AS max_lock_waits,
AVG(deadlocks) AS avg_deadlocks,
MAX(deadlocks) AS max_deadlocks
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE)
ORDER BY collection_date;
GO
— 2. 找出有锁等待或死锁的时间段
SELECT
collection_time,
lock_waits,
deadlocks,
user_connections,
batch_requests_per_sec
FROM msdb.dbo.sqlserver_monitoring
WHERE lock_waits > 0 OR deadlocks > 0
ORDER BY collection_time DESC;
GO
— 步骤6:生成性能报告
— 1. 生成每日性能报告
SELECT
CAST(collection_time AS DATE) AS collection_date,
AVG(cpu_usage) AS avg_cpu_usage,
MAX(cpu_usage) AS max_cpu_usage,
AVG(memory_usage) AS avg_memory_usage,
MAX(memory_usage) AS max_memory_usage,
AVG(io_stall_ms) AS avg_io_stall_ms,
MAX(io_stall_ms) AS max_io_stall_ms,
AVG(user_connections) AS avg_user_connections,
MAX(user_connections) AS max_user_connections,
AVG(batch_requests_per_sec) AS avg_batch_requests_per_sec,
MAX(batch_requests_per_sec) AS max_batch_requests_per_sec,
AVG(page_life_expectancy) AS avg_page_life_expectancy,
AVG(lock_waits) AS avg_lock_waits,
MAX(lock_waits) AS max_lock_waits,
AVG(deadlocks) AS avg_deadlocks,
MAX(deadlocks) AS max_deadlocks
FROM msdb.dbo.sqlserver_monitoring
WHERE collection_time > DATEADD(DAY, -7, GETDATE())
GROUP BY CAST(collection_time AS DATE)
ORDER BY collection_date;
GO
执行结果:
————— ————— ———– ————- ————- ————-
2025-04-02 2025-04-02 0 10.25 15.00 5.50
2025-04-02 2025-04-02 1 8.75 12.00 5.50
…
2025-04-08 2025-04-08 10 15.50 20.00 11.00
(168 rows affected)
collection_time cpu_usage memory_usage user_connections batch_requests_per_sec
————————- ——— ———— —————- ——————–
2025-04-05 14:00:00.000 85.50 88.75 85 450
2025-04-06 15:30:00.000 82.25 86.50 80 420
(10 rows affected)
collection_date collection_date avg_memory_usage max_memory_usage min_memory_usage avg_page_life_expectancy
————— ————— —————- —————- —————- ————————
2025-04-02 2025-04-02 65.25 75.00 55.00 320
2025-04-03 2025-04-03 68.75 80.00 58.00 310
…
2025-04-08 2025-04-08 70.25 78.00 62.00 350
(7 rows affected)
collection_time memory_usage
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
