在SQL Server 2012 Standard版中,我知道用户连接的最大数量为32,767。

当前要连接30,000个用户,而且这个数字还会增加。



评论

如果这些来自应用程序,则应用程序应在完成后关闭其连接。保持连接断开是达到此限制的可能原因

#1 楼

SQL Server版本之间的最大连接数为32,767。

您可以通过查看以下内容来确定SQL Server当前具有的连接数:

SELECT ConnectionStatus = CASE WHEN dec.most_recent_sql_handle = 0x0 
        THEN 'Unused' 
        ELSE 'Used' 
        END
    , CASE WHEN des.status = 'Sleeping' 
        THEN 'sleeping' 
        ELSE 'Not Sleeping' 
        END
    , ConnectionCount = COUNT(1)
FROM sys.dm_exec_connections dec
    INNER JOIN sys.dm_exec_sessions des ON dec.session_id = des.session_id
GROUP BY CASE WHEN des.status = 'Sleeping' 
        THEN 'sleeping' 
        ELSE 'Not Sleeping' 
        END
    , CASE WHEN dec.most_recent_sql_handle = 0x0 
        THEN 'Unused' 
        ELSE 'Used' 
        END;


如果考虑到上述查询中已用和未用连接之间的比率,则很可能连接到服务器的客户端应用程序启用了连接池,并且这些连接没有得到有效利用。您可能希望开发人员修改这些应用程序的连接字符串,以限制连接池的大小,并确保它们正确处理了连接。如果未正确处理连接,则只要客户端应用程序正在运行,它们就会保持打开状态。

如果您感到特别狂躁,需要摆脱所有未执行的连接最近的任何内容(无论他们当前是否正在执行工作),都可以运行以下代码,这些代码将生成可以终止的会话列表。您需要将生成的命令复制并粘贴到新的SSMS窗口中,以实际运行命令。我还建议您更新您的简历,以防万一。



DECLARE @cmd NVARCHAR(MAX);
SET @cmd = '';
SELECT @cmd = @cmd + 
    CASE WHEN @cmd = '' THEN '' ELSE CHAR(13) + CHAR(10) END 
    + 'KILL ' + CONVERT(VARCHAR(MAX), dec.session_id) + ';'
FROM sys.dm_exec_connections dec
WHERE dec.most_recent_sql_handle = 0x0;

PRINT @cmd;



可以通过在多个SQL Server节点之间分片数据,线性地将连接数量扩展到超过32,767。但是,在我看来,使用分片来绕开连接数量限制的方法类似于使用原子弹杀死蜘蛛。它会杀死蜘蛛,但最终您可能会遇到更大的问题。更何况要制造原子弹是相当困难的,更不用说正确实现工具分片了。

评论


您能解释为什么我们应该通过在sys.dm_exec_connections中使用most_recent_sql_handle而不是在sys.dm_exec_sessions中使用status和last_request_start_time和is_user_process来标识“可杀死的”会话吗?似乎是一个奇怪的选择。

–迈克·谢里尔(Mike Sherrill)的“猫召回”
17年3月14日在19:56

@Mike,这是个好点-当时我纯粹是在考虑由连接池打开并且从未使用过的连接。添加is_user_process限定词是一个好主意,并且当然不会排除last_request_start_time是最近的会话。最近多久?另一个好问题。

– Max Vernon♦
17年3月14日在20:38

last_request_start_time应该较旧而不是较新。我认为一个安全的“可杀死的”用户会话将是正在休眠并且几天没有请求的会话。我猜截止时间取决于我们的应用程序员在清理自己之后的能力。

–迈克·谢里尔(Mike Sherrill)的“猫召回”
17 Mar 14 '17 at 20:52

#2 楼

过去,我在连接池方面遇到了奇怪的问题,您的情况与其中一种情况非常吻合。如果您的应用程序正在使用连接池(目前仍在推测,直到您确认或拒绝),然后您将有许多连接保持打开状态。这是设计使然。

连接池旨在减少创建数据库连接的开销。以一个3的连接池为例,据我所知,生命周期是这样的(从冷连接池缓存开始):


应用程序用户A询问用于连接到数据库
连接池启动到数据库的连接线程1
应用程序用户B请求连接到数据库
连接池启动到数据库的连接线程2
应用程序用户A关闭与连接池的连接...

应用程序用户C请求与数据库的连接
连接池在线程1上发出sp_reset_connection
连接池分配线程1对应用程序用户C

这是一个过分的简化,但要点包括:


连接将在连接池线程池和数据库之间保持打开状态直到数据库或连接池强行关闭连接
连接保持打开状态,并且最后一个会话执行上下文t,直到该线程被另一个用户重新使用为止,此时将调用sp_reset_connection

这是我用来得出这些结论的参考资料。

SQL Server DBA的连接池

孤立事务的情况
/>