SQLServer教程FG071-SQLServer连接池优化实战
本文档风哥主要介绍SQLServer数据库连接池优化相关知识,包括SQLServer数据库连接池的概念、SQLServer数据库连接池工作原理、SQLServer数据库连接池核心参数配置、SQLServer数据库连接池监控与问题排查等内容,风哥教程参考SQLServer官方文档Database Engine、Administration内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 SQLServer数据库连接池概念
SQLServer数据库连接池(Connection Pool)是一种数据库连接管理机制,通过预先创建并维护一定数量的数据库连接,避免频繁创建和销毁连接带来的性能开销。连接池在应用程序和数据库之间充当中间层,有效提升系统性能和资源利用率。更多视频教程www.fgedu.net.cn
- 减少连接创建开销,提升响应速度
- 控制并发连接数,保护数据库资源
- 连接复用,降低系统负载
- 支持连接验证和健康检查
- 提供连接超时和等待队列机制
1.2 SQLServer数据库连接池工作原理
SQLServer数据库连接池工作原理:
- 连接创建:应用程序首次请求连接时,连接池创建新连接
- 连接复用:连接使用完毕后归还池中,供其他请求复用
- 连接验证:从池中获取连接时验证连接有效性
- 连接回收:空闲超时的连接被自动回收销毁
- 连接扩展:连接不足时按需创建新连接至最大值
应用程序请求连接
|
v
+——————+
| 连接池检查 |
+——————+
|
+– 有空闲连接 –> 验证连接 –> 返回连接
|
+– 无空闲连接 –> 创建新连接(未达最大值) –> 返回连接
|
+– 已达最大值 –> 等待队列 –> 超时报错
应用程序释放连接
|
v
+——————+
| 连接归还池中 |
+——————+
|
+– 空闲超时 –> 销毁连接
|
+– 未超时 –> 保留待复用
1.3 SQLServer数据库连接池核心参数
SQLServer数据库连接池核心参数说明:
Min Pool Size 最小连接数,默认0
Max Pool Size 最大连接数,默认100
Connect Timeout 连接超时时间,默认15秒
Connection Lifetime 连接生命周期,默认0(无限)
Pooling 是否启用连接池,默认true
Connection Reset 连接重置,默认true
# JDBC连接池核心参数
maxPoolSize 最大连接数
minPoolSize 最小连接数
acquireIncrement 连接增长步长
maxIdleTime 最大空闲时间
checkoutTimeout 获取连接超时时间
idleConnectionTestPeriod 空闲连接检测周期
# SQLServer服务器端参数
user connections 最大用户连接数,默认32767
max worker threads 最大工作线程数,默认0(自动)
Part02-生产环境规划与建议
2.1 SQLServer数据库连接池规划
SQLServer数据库连接池规划要点:
最小连接数 = 核心业务并发数 × 1.2
最大连接数 = 峰值业务并发数 × 1.5
# 不同场景规划建议
小型应用(并发<50):
Min Pool Size: 5
Max Pool Size: 50
中型应用(并发50-200):
Min Pool Size: 20
Max Pool Size: 150
大型应用(并发200-500):
Min Pool Size: 50
Max Pool Size: 300
超大型应用(并发>500):
Min Pool Size: 100
Max Pool Size: 500
# 注意事项
– 最大连接数不超过服务器user connections配置
– 考虑多应用实例共享数据库的情况
– 预留管理连接和系统连接
– 考虑连接泄漏的缓冲空间
2.2 SQLServer数据库连接池配置建议
SQLServer数据库连接池配置建议:
Server=192.168.1.100;Database=fgedudb;
User ID=fgedu;Password=fgedu123;
Min Pool Size=20;
Max Pool Size=150;
Connect Timeout=30;
Connection Lifetime=600;
Pooling=true;
# JDBC连接池配置示例(c3p0)
jdbcUrl=jdbc:sqlserver://192.168.1.100:1433;databaseName=fgedudb
user=fgedu
password=fgedu123
minPoolSize=20
maxPoolSize=150
acquireIncrement=10
maxIdleTime=600
checkoutTimeout=30000
idleConnectionTestPeriod=60
# HikariCP连接池配置示例
jdbcUrl=jdbc:sqlserver://192.168.1.100:1433;databaseName=fgedudb
username=fgedu
password=fgedu123
minimumIdle=20
maximumPoolSize=150
connectionTimeout=30000
idleTimeout=600000
maxLifetime=1800000
2.3 SQLServer数据库连接池监控策略
SQLServer数据库连接池监控策略:
- 连接数监控:监控当前连接数、活跃连接数、空闲连接数
- 等待监控:监控连接等待时间、等待队列长度
- 错误监控:监控连接超时、连接失败次数
- 性能监控:监控连接获取时间、连接使用时长
- 资源监控:监控数据库服务器CPU、内存、网络
Part03-生产环境项目实施方案
3.1 SQLServer数据库连接池状态查看
3.1.1 SQLServer数据库查看当前连接数
SELECT
DB_NAME(dbid) AS DatabaseName,
COUNT(*) AS ConnectionCount,
hostname AS HostName,
program_name AS ProgramName,
loginame AS LoginName
FROM sys.sysprocesses
WHERE dbid > 0
GROUP BY DB_NAME(dbid), hostname, program_name, loginame
ORDER BY ConnectionCount DESC;
GO
DatabaseName ConnectionCount HostName ProgramName LoginName
———— ————— —————- ——————– ———-
fgedudb 85 APP-SERVER-01 .Net SqlClient fgedu
fgedudb 42 APP-SERVER-02 .Net SqlClient fgedu
master 5 DB-SERVER-01 Microsoft SQL Server sa
fgedudb 3 APP-SERVER-03 JDBC-SQLServer fgedu
# 查看详细连接信息
SELECT
session_id,
DB_NAME(database_id) AS DatabaseName,
host_name,
program_name,
login_name,
status,
cpu_time,
memory_usage,
total_scheduled_time,
total_elapsed_time,
last_request_start_time,
last_request_end_time
FROM sys.dm_exec_sessions
WHERE is_user_process = 1
ORDER BY session_id;
GO
session_id DatabaseName host_name program_name login_name status cpu_time memory_usage
———- ———— ————- —————- ———- —— ———- ———–
51 fgedudb APP-SERVER-01 .Net SqlClient fgedu running 125 2
52 fgedudb APP-SERVER-01 .Net SqlClient fgedu sleeping 0 1
53 fgedudb APP-SERVER-02 .Net SqlClient fgedu running 89 2
54 fgedudb APP-SERVER-02 .Net SqlClient fgedu sleeping 0 1
3.1.2 SQLServer数据库查看连接配置
EXEC sp_configure ‘user connections’;
GO
name minimum maximum config_value run_value
——————– ——— ———– ———— ———
user connections 0 32767 0 32767
# 查看当前连接数统计
SELECT
@@MAX_CONNECTIONS AS MaxConnections,
@@CONNECTIONS AS TotalConnectionsSinceStartup,
(SELECT COUNT(*) FROM sys.dm_exec_sessions) AS CurrentSessions,
(SELECT COUNT(*) FROM sys.dm_exec_connections) AS CurrentConnections;
GO
MaxConnections TotalConnectionsSinceStartup CurrentSessions CurrentConnections
————– —————————- ————— —————–
32767 1523456 135 132
# 查看工作线程配置
EXEC sp_configure ‘max worker threads’;
GO
name minimum maximum config_value run_value
——————– ——— ———– ———— ———
max worker threads 128 65535 0 512
3.2 SQLServer数据库连接池优化配置
3.2.1 SQLServer数据库服务器端优化
EXEC sp_configure ‘user connections’, 500;
RECONFIGURE;
GO
Configuration option ‘user connections’ changed from 0 to 500.
Run the RECONFIGURE statement to install.
# 配置最大工作线程数
EXEC sp_configure ‘max worker threads’, 1024;
RECONFIGURE;
GO
Configuration option ‘max worker threads’ changed from 0 to 1024.
Run the RECONFIGURE statement to install.
# 查看配置生效情况
EXEC sp_configure ‘user connections’;
EXEC sp_configure ‘max worker threads’;
GO
name minimum maximum config_value run_value
——————– ——— ———– ———— ———
user connections 0 32767 500 500
max worker threads 128 65535 1024 1024
3.2.2 SQLServer数据库连接超时优化
EXEC sp_configure ‘remote login timeout (s)’;
GO
name minimum maximum config_value run_value
————————– ——— ———– ———— ———
remote login timeout (s) 0 2147483647 10 10
# 设置远程登录超时时间
EXEC sp_configure ‘remote login timeout (s)’, 30;
RECONFIGURE;
GO
Configuration option ‘remote login timeout (s)’ changed from 10 to 30.
Run the RECONFIGURE statement to install.
# 查看查询等待配置
EXEC sp_configure ‘query wait (s)’;
GO
name minimum maximum config_value run_value
——————– ——— ———– ———— ———
query wait (s) -1 2147483647 -1 -1
3.3 SQLServer数据库连接池问题排查
3.3.1 SQLServer数据库排查连接等待问题
SELECT
session_id,
wait_type,
wait_time,
wait_resource,
DB_NAME(database_id) AS DatabaseName,
host_name,
program_name,
status
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
WHERE wait_type LIKE ‘%CONNECT%’ OR wait_type LIKE ‘%LOGIN%’
ORDER BY wait_time DESC;
GO
session_id wait_type wait_time wait_resource DatabaseName host_name program_name status
———- —————– ——— —————– ———— ————- ————– ——-
125 SOS_SCHEDULER_YIELD 15000 fgedudb APP-SERVER-01 .Net SqlClient running
126 RESOURCE_SEMAPHORE 12000 fgedudb APP-SERVER-02 .Net SqlClient running
# 查看连接相关等待统计
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
max_wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type IN (
‘SOS_SCHEDULER_YIELD’,
‘RESOURCE_SEMAPHORE’,
‘THREADPOOL’,
‘CMEMTHREAD’,
‘CXPACKET’
)
ORDER BY wait_time_ms DESC;
GO
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms
——————– ——————- ———— —————- ——————-
SOS_SCHEDULER_YIELD 125678 5678900 45000 123456
RESOURCE_SEMAPHORE 12345 1234567 30000 23456
THREADPOOL 5678 456789 25000 12345
Part04-生产案例与实战讲解
4.1 SQLServer数据库连接池耗尽案例
# 错误信息:Timeout expired. The timeout period elapsed prior to
# obtaining a connection from the pool.
# 分析步骤:
# 1. 查看当前连接状态
SELECT
DB_NAME(dbid) AS DatabaseName,
COUNT(*) AS ConnectionCount,
status,
hostname
FROM sys.sysprocesses
WHERE dbid = DB_ID(‘fgedudb’)
GROUP BY DB_NAME(dbid), status, hostname
ORDER BY ConnectionCount DESC;
GO
DatabaseName ConnectionCount status hostname
———— ————— ——– ————
fgedudb 150 sleeping APP-SERVER-01
fgedudb 45 sleeping APP-SERVER-02
fgedudb 5 running APP-SERVER-01
# 2. 查看长时间空闲连接
SELECT
session_id,
DB_NAME(database_id) AS DatabaseName,
host_name,
program_name,
status,
DATEDIFF(MINUTE, last_request_end_time, GETDATE()) AS IdleMinutes,
last_request_end_time
FROM sys.dm_exec_sessions
WHERE database_id = DB_ID(‘fgedudb’)
AND status = ‘sleeping’
AND DATEDIFF(MINUTE, last_request_end_time, GETDATE()) > 30
ORDER BY IdleMinutes DESC;
GO
session_id DatabaseName host_name program_name status IdleMinutes last_request_end_time
———- ———— ————- ————– ——- ———– ——————–
78 fgedudb APP-SERVER-01 .Net SqlClient sleeping 125 2026-04-07 08:30:00
82 fgedudb APP-SERVER-01 .Net SqlClient sleeping 98 2026-04-07 08:57:00
95 fgedudb APP-SERVER-02 .Net SqlClient sleeping 67 2026-04-07 09:28:00
# 3. 解决方案:清理长时间空闲连接
— 创建清理脚本
DECLARE @sql NVARCHAR(MAX) = ”;
SELECT @sql = @sql + ‘KILL ‘ + CAST(session_id AS VARCHAR) + ‘; ‘
FROM sys.dm_exec_sessions
WHERE database_id = DB_ID(‘fgedudb’)
AND status = ‘sleeping’
AND DATEDIFF(MINUTE, last_request_end_time, GETDATE()) > 60;
EXEC(@sql);
GO
# 4. 优化连接池配置
— 应用端连接字符串调整
— Max Pool Size=200 (从150增加)
— Connection Lifetime=1800 (30分钟自动回收)
— Connection Reset=true (连接重置)
4.2 SQLServer数据库连接泄漏案例
# 分析步骤:
# 1. 监控连接数变化
— 创建监控脚本
SELECT
GETDATE() AS CheckTime,
DB_NAME(database_id) AS DatabaseName,
COUNT(*) AS ConnectionCount,
SUM(CASE WHEN status = ‘running’ THEN 1 ELSE 0 END) AS ActiveCount,
SUM(CASE WHEN status = ‘sleeping’ THEN 1 ELSE 0 END) AS SleepingCount
FROM sys.dm_exec_sessions
WHERE database_id = DB_ID(‘fgedudb’)
GROUP BY DB_NAME(database_id);
GO
CheckTime DatabaseName ConnectionCount ActiveCount SleepingCount
———————– ———— ————— ———– ————-
2026-04-08 10:00:00 fgedudb 150 5 145
2026-04-08 11:00:00 fgedudb 180 8 172
2026-04-08 12:00:00 fgedudb 210 6 204
2026-04-08 13:00:00 fgedudb 245 7 238
# 2. 分析连接来源
SELECT
host_name,
program_name,
COUNT(*) AS ConnectionCount,
MIN(login_time) AS FirstLogin,
MAX(login_time) AS LastLogin
FROM sys.dm_exec_sessions
WHERE database_id = DB_ID(‘fgedudb’)
GROUP BY host_name, program_name
ORDER BY ConnectionCount DESC;
GO
host_name program_name ConnectionCount FirstLogin LastLogin
————- ————– ————— ——————— ———————
APP-SERVER-01 .Net SqlClient 180 2026-04-08 08:00:00 2026-04-08 13:00:00
APP-SERVER-02 .Net SqlClient 65 2026-04-08 08:05:00 2026-04-08 13:00:00
# 3. 排查应用代码问题
— 检查是否有未关闭的连接
— 确保使用using语句或try-finally关闭连接
— 检查连接池配置是否合理
# 4. 解决方案
— 应用代码修改示例(C#)
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
// 执行数据库操作
// 连接会自动关闭和释放
}
— 配置连接池参数
Min Pool Size=20
Max Pool Size=200
Connection Lifetime=1800
Connection Reset=true
Pooling=true
4.3 SQLServer数据库连接池优化方案
SQLServer数据库连接池优化综合方案:
— 配置合理的最大连接数
EXEC sp_configure ‘user connections’, 500;
RECONFIGURE;
— 配置工作线程数
EXEC sp_configure ‘max worker threads’, 1024;
RECONFIGURE;
— 配置内存
EXEC sp_configure ‘min server memory (MB)’, 4096;
EXEC sp_configure ‘max server memory (MB)’, 16384;
RECONFIGURE;
# 2. 应用端优化
— 连接字符串配置
Server=192.168.1.100;Database=fgedudb;
User ID=fgedu;Password=fgedu123;
Min Pool Size=20;
Max Pool Size=200;
Connect Timeout=30;
Connection Lifetime=1800;
Connection Reset=true;
Pooling=true;
# 3. 监控脚本
— 创建连接池监控存储过程
CREATE PROCEDURE sp_fgedu_monitor_connections
AS
BEGIN
SELECT
GETDATE() AS CheckTime,
DB_NAME(database_id) AS DatabaseName,
COUNT(*) AS TotalConnections,
SUM(CASE WHEN status = ‘running’ THEN 1 ELSE 0 END) AS ActiveConnections,
SUM(CASE WHEN status = ‘sleeping’ THEN 1 ELSE 0 END) AS SleepingConnections,
SUM(CASE WHEN DATEDIFF(MINUTE, last_request_end_time, GETDATE()) > 30
THEN 1 ELSE 0 END) AS LongIdleConnections
FROM sys.dm_exec_sessions
WHERE is_user_process = 1
GROUP BY DB_NAME(database_id);
END;
GO
Command(s) completed successfully.
— 执行监控
EXEC sp_fgedu_monitor_connections;
GO
CheckTime DatabaseName TotalConnections ActiveConnections SleepingConnections LongIdleConnections
———————– ———— —————- —————– ——————- ——————-
2026-04-08 14:00:00 fgedudb 185 12 173 45
2026-04-08 14:00:00 master 8 2 6 0
Part05-风哥经验总结与分享
5.1 SQLServer数据库连接池最佳实践
SQLServer数据库连接池最佳实践:
- 合理配置连接池大小:根据业务并发量配置最小和最大连接数
- 设置连接超时:避免长时间等待连接导致请求超时
- 启用连接重置:确保从池中获取的连接状态干净
- 设置连接生命周期:定期回收长时间使用的连接
- 监控连接使用:建立监控体系及时发现连接问题
- 代码规范:确保所有连接正确关闭和释放
5.2 SQLServer数据库连接池检查清单
1. 服务器端配置检查
[ ] user connections配置是否合理
[ ] max worker threads配置是否合理
[ ] 内存配置是否充足
[ ] CPU资源是否充足
2. 应用端配置检查
[ ] 连接池大小配置是否合理
[ ] 连接超时配置是否合理
[ ] 连接生命周期配置是否合理
[ ] 连接重置是否启用
3. 监控检查
[ ] 是否有连接池监控
[ ] 是否有连接告警
[ ] 是否定期检查连接状态
[ ] 是否有连接泄漏检测
4. 代码检查
[ ] 是否正确关闭连接
[ ] 是否使用using语句
[ ] 是否有异常处理
[ ] 是否有连接泄漏风险
5. 性能检查
[ ] 连接获取时间是否正常
[ ] 连接等待是否频繁
[ ] 连接池是否经常满
[ ] 是否有空闲连接过多
5.3 SQLServer数据库连接池管理工具推荐
SQLServer数据库连接池管理工具推荐:
- SQL Server Management Studio:查看连接状态和会话信息
- 动态管理视图:sys.dm_exec_sessions、sys.dm_exec_connections
- 性能计数器:监控连接池性能指标
- 应用程序监控:APM工具监控连接池使用情况
- 自定义脚本:定期检查和清理连接
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
