如果一个连接 returns 到池,而线程被阻塞等待创建新连接,是否会使用返回的连接?
If a connection returns to the pool while a thread is blocked waiting on a new connection to be created, will the returned connection be used?
基本上我正在考虑的情况如下:
假设创建新连接需要大量时间。
所有连接都在使用中,一个线程请求新连接。
当线程等待建立新连接时,连接 returns 到池。
线程是等待建立新连接并使用它还是立即解除阻塞并使用返回的连接。
我试图对此进行测试,但我无法在 2 个线程之间获得正确的时间(连接时间变化很大)。
如果我理解你的问题:
While the thread is waiting for the new connection to be made, a connection returns to the pool.
我对 ADO.Net 和 SQL 服务器驱动程序如何工作的理解是,如果线程“正在等待新连接”已经是处于 connecting
状态的 thread/process 中的活动连接对象。 ADO.Net 连接管理器和 SQL 服务器驱动程序都没有任何工具可以将连接对象“切换”为池中的另一个连接对象(如果某个连接对象可用)。
因此,一旦您启动连接,您就会保留该对象,直到您关闭它(或以其他方式丢弃它)。
此外,您可能已经知道这一点,但池中的连接实际上并未断开连接,而是处于 inactive 状态,在该状态下它们物理连接但未记录-进入服务器。
这是错误的正如评论中所指出的,会话 ID 不同。
我想出了一个简单的方法来测试它。真不敢相信我之前没有想到这一点。
结果显示,如果连接 returns 到池(并使用返回的连接),等待新连接完成创建的阻塞线程将解除阻塞!
对于那些想知道的人,正在启动的新连接仍被添加到连接池中。
代码如下:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Diagnostics;
namespace General_Testing
{
class Program
{
private static volatile bool returned = false;
private static string connStr = "your connection string here";
static void Main(string[] args)
{
Thread t1 = new Thread(thread1);
Thread t2 = new Thread(thread2);
t1.Start();
t2.Start();
}
private static void thread1()
{
Stopwatch sw = new Stopwatch();
sw.Restart();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
returned = true;
sw.Stop();
Console.WriteLine("Thread1 created thread in " + sw.ElapsedMilliseconds + "ms");
Thread.Sleep(50); //new connection takes much longer than 50ms to be created
}
}
private static void thread2()
{
while (!returned) ;
Stopwatch sw = new Stopwatch();
sw.Restart();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
Console.WriteLine("Thread2 created thread in " + sw.ElapsedMilliseconds + "ms");
}
}
}
}
结果如下:
Thread1 created thread in 2098ms
Thread2 created thread in 194ms
基本上我正在考虑的情况如下:
假设创建新连接需要大量时间。
所有连接都在使用中,一个线程请求新连接。
当线程等待建立新连接时,连接 returns 到池。
线程是等待建立新连接并使用它还是立即解除阻塞并使用返回的连接。
我试图对此进行测试,但我无法在 2 个线程之间获得正确的时间(连接时间变化很大)。
如果我理解你的问题:
While the thread is waiting for the new connection to be made, a connection returns to the pool.
我对 ADO.Net 和 SQL 服务器驱动程序如何工作的理解是,如果线程“正在等待新连接”已经是处于 connecting
状态的 thread/process 中的活动连接对象。 ADO.Net 连接管理器和 SQL 服务器驱动程序都没有任何工具可以将连接对象“切换”为池中的另一个连接对象(如果某个连接对象可用)。
因此,一旦您启动连接,您就会保留该对象,直到您关闭它(或以其他方式丢弃它)。
此外,您可能已经知道这一点,但池中的连接实际上并未断开连接,而是处于 inactive 状态,在该状态下它们物理连接但未记录-进入服务器。
这是错误的正如评论中所指出的,会话 ID 不同。
我想出了一个简单的方法来测试它。真不敢相信我之前没有想到这一点。
结果显示,如果连接 returns 到池(并使用返回的连接),等待新连接完成创建的阻塞线程将解除阻塞!
对于那些想知道的人,正在启动的新连接仍被添加到连接池中。
代码如下:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Diagnostics;
namespace General_Testing
{
class Program
{
private static volatile bool returned = false;
private static string connStr = "your connection string here";
static void Main(string[] args)
{
Thread t1 = new Thread(thread1);
Thread t2 = new Thread(thread2);
t1.Start();
t2.Start();
}
private static void thread1()
{
Stopwatch sw = new Stopwatch();
sw.Restart();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
returned = true;
sw.Stop();
Console.WriteLine("Thread1 created thread in " + sw.ElapsedMilliseconds + "ms");
Thread.Sleep(50); //new connection takes much longer than 50ms to be created
}
}
private static void thread2()
{
while (!returned) ;
Stopwatch sw = new Stopwatch();
sw.Restart();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
Console.WriteLine("Thread2 created thread in " + sw.ElapsedMilliseconds + "ms");
}
}
}
}
结果如下:
Thread1 created thread in 2098ms
Thread2 created thread in 194ms