Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 连续运行应用程序上的SQL Server连接池_C#_Sql Server_Multithreading_Connection Pooling - Fatal编程技术网

C# 连续运行应用程序上的SQL Server连接池

C# 连续运行应用程序上的SQL Server连接池,c#,sql-server,multithreading,connection-pooling,C#,Sql Server,Multithreading,Connection Pooling,我有问题的连接拉与持续运行的程序。当我在任务中对数据库进行大量查询(每4分钟5次(查询3个表并将结果保存到一个表))时,就会出现问题。连接池的最大池连接大小已用完。奇怪的是,我在DB100上等待特定连接字符串/机器/用户条目的命令条目。我的理解是,等待命令意味着这个连接可以重用,但由于某种奇怪的未知原因,当从任务运行命令时,我无法重用可用的连接,他们只是不等待任何人,并且在一段时间后出现错误,我已达到最大池连接大小 迄今为止的假设: 从tasks DB运行命令时,将其解释为无效,以重用可用连接

我有问题的连接拉与持续运行的程序。当我在任务中对数据库进行大量查询(每4分钟5次(查询3个表并将结果保存到一个表))时,就会出现问题。连接池的最大池连接大小已用完。奇怪的是,我在DB100上等待特定连接字符串/机器/用户条目的命令条目。我的理解是,等待命令意味着这个连接可以重用,但由于某种奇怪的未知原因,当从任务运行命令时,我无法重用可用的连接,他们只是不等待任何人,并且在一段时间后出现错误,我已达到最大池连接大小

迄今为止的假设:

  • 从tasks DB运行命令时,将其解释为无效,以重用可用连接

  • 连接没有关闭,但为什么?似乎要使用关键字来关闭它们。超过100条命令正在等待数据库中的一条命令

  • 由于某种原因,处理程序没有被垃圾收集?但是100 AC告诉了其他一些事情

  • 更新:LOCALDB观察/总结:

    当我试图在本地DBSQLServerExpress上复制时,这个问题会在非常尴尬的情况下发生。我不得不添加Thread.Sleep(600000)来模拟这种情况。最终,我得到了最大池错误,但在本例中,所有连接都是打开的,因此这是不言自明的

    在local->server场景中,我不认为一次可以打开100个连接,而是因为某种原因而保持打开状态。当在localMachine->serverDB环境下启动这个程序时,我甚至不需要添加Thread.Sleep(600000)来使程序崩溃

    所有这些都是我基于观察的假设。我想不出在我的连续运行的服务中,每4分钟查询一次数据库,会出现什么情况

    在我的全部本地测试之后,我很困惑等待命令是否意味着这个连接可以重用

    更新2忘记了在我最终遇到这个最大池错误之前,我的初始程序可以运行几天

    以下是可能产生此类问题的程序:

     using System;
     using System.Data.SqlClient;
     using System.Threading;
     using System.Threading.Tasks;
    
     namespace Pooling
     {
       class Program
       {
          private static int connectionIterations;
    
          private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True";
    
        static void Main(string[] args)
        {
            try
            {
                Iterations();
    
                while(true)
                {
                    ConnectionSnowball();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
    
        private static void ConnectionSnowball()
        {
            Parallel.For(0, connectionIterations, i =>
            {
                try
                {
                    Console.WriteLine($"Connection id: {i}");
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        SqlCommand cmd = new SqlCommand("SELECT 1 FROM test_table", connection);
                        connection.Open();
                        cmd.ExecuteNonQuery();
                        Thread.Sleep(600000);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });
        }
    
        private static void Iterations()
        {
            connectionIterations = 200;
        }
    }
    }
    

    我调试了你的代码,没有发现连接泄漏。您只是有一个连接池溢出。我为您检查了两种可能的解决方案

    禁用池连接

    private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True;Pooling=False";
    
    增加连接池

    private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True;Max Pool Size=200";
    
    要测试在调用
    ConnectionSnowball()
    之前、期间和之后连接的增加和减少方式,可以使用此SQL查询

    select count(1) from sys.dm_exec_sessions where database_id = DB_ID(N'localDB')
    
    有关连接字符串参数的详细信息


    其他可能的解决办法是使用。对于此任务,这可能是一个更合适的解决方案,因为大量连接非常占用资源。

    似乎缺少释放/处置资源。您是否尝试过在SqlCommand周围使用进行
    ?根据查询持续时间的不同,连接数200可能会超过100。请注意,您无法通过从服务器查看来判断连接是否在池中且可供使用,或者连接是否正在由客户端使用但当前未提供命令。这段信息只存在于客户端——只要一个物理连接正被一个未经分解的
    SqlConnection
    实例使用,它就在使用中;否则就不是了。若要查看客户端上是否存在资源泄漏,请创建一个转储文件,并分析
    SqlConnection
    实例的堆以及使它们保持活动状态的GC根。@FrankNielsen我将尝试此方法。我认为这不能挂起SqlConnection,如果不使用。不过,这是事实。当您删除并行时,它将始终使用精确的一个连接,这意味着没有连接泄漏。当您切换到任务和连接时,从15 ie开始,比稳定和粗暴地上升,直到最大池大小。任务可能是问题所在。另一个不太可能检查的问题是,每次创建新连接时都使用相同的连接字符串(如中,字符对字符相同),因为这就是池连接的关键所在。