具体的原因,我们来看代码(用reflector反编译.net framework 2.0的dll)
dbconn有一个方法叫做:Open,部分代码如下:
1
try
2
{
3
statistics = SqlStatistics.StartTimer(this.Statistics);
4
this.InnerConnection.OpenConnection(this, this.ConnectionFactory);
5
SqlInternalConnectionSmi innerConnection = this.InnerConnection as SqlInternalConnectionSmi;
6
if (innerConnection != null)
7
{
8
innerConnection.AutomaticEnlistment();
9
}
10
注意上面的第4行,this.InnerConnection.OpenConnection(this, this.ConnectionFactory);这里的this.ConnectionFactory是一个DbConnectionFactory类型,定义在class SqlConnection中
2

3

4

5

6

7

8

9

10













1
try
2
{
3
connectionFactory.PermissionDemand(outerConnection);
4
to = connectionFactory.GetConnection(outerConnection);
5
}
6
catch
7
{
8
connectionFactory.SetInnerConnectionTo(outerConnection, this);
9
throw;
10
}
看一下第4行,哈,这里绕到了我们上面的conn factory,我们看它里面的GetConnection怎么写的?(class DbConnectionFactory)
2

3

4

5

6

7

8

9

10

1
internal DbConnectionInternal GetConnection(DbConnection owningConnection)
2
{
3
DbConnectionInternal connection;
4
DbConnectionPoolGroup connectionPoolGroup = this.GetConnectionPoolGroup(owningConnection);
5
DbConnectionPool connectionPool = this.GetConnectionPool(owningConnection, connectionPoolGroup);
6
if (connectionPool == null)
7
{
8
connectionPoolGroup = this.GetConnectionPoolGroup(owningConnection);
9
connection = this.CreateNonPooledConnection(owningConnection, connectionPoolGroup);
10
this.PerformanceCounters.NumberOfNonPooledConnections.Increment();
11
return connection;
12
}
13
connection = connectionPool.GetConnection(owningConnection);
14
if (connection == null)
15
{
16
Bid.Trace("<prov.DbConnectionFactory.GetConnection|RES|CPOOL> %d#, GetConnection failed because a pool timeout occurred.\n", this.ObjectID);
17
throw ADP.PooledOpenTimeout();
18
}
19
return connection;
20
}
注意第5行里面的GetConnectionPool的调用,继续看它内部的代码:(class DbConnectionFactory)
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

1
private DbConnectionPool GetConnectionPool(DbConnection owningObject, DbConnectionPoolGroup connectionPoolGroup)
2
{
3
if (connectionPoolGroup.IsDisabled && (connectionPoolGroup.PoolGroupOptions != null))
4
{
5
Bid.Trace("<prov.DbConnectionFactory.GetConnectionPool|RES|INFO|CPOOL> %d#, DisabledPoolGroup=%d#\n", this.ObjectID, connectionPoolGroup.ObjectID);
6
DbConnectionPoolGroupOptions poolGroupOptions = connectionPoolGroup.PoolGroupOptions;
7
DbConnectionOptions connectionOptions = connectionPoolGroup.ConnectionOptions;
8
string connectionString = connectionOptions.UsersConnectionString(false);
9
connectionPoolGroup = this.GetConnectionPoolGroup(connectionString, poolGroupOptions, ref connectionOptions);
10
this.SetConnectionPoolGroup(owningObject, connectionPoolGroup);
11
}
12
return connectionPoolGroup.GetConnectionPool(this);
13
}
注意第9行,我们go on...(Class DbConnectionFactory)
2

3

4

5

6

7

8

9

10

11

12

13

1
if ((poolOptions == null) && ADP.IsWindowsNT)
2
{
3
if (group != null)
4
{
5
poolOptions = group.PoolGroupOptions;
6
}
7
else
8
{
9
poolOptions = this.CreateConnectionPoolGroupOptions(options);
10
}
11
}
12
依然是第9行(枯燥的数字。。。),继续往里面看:(Class DbConnectionFactory)
2

3

4

5

6

7

8

9

10

11

12



















1
internal SqlConnectionString(string connectionString) : base(connectionString, GetParseSynonyms(), false)
2
{
3
bool inProc = InOutOfProcHelper.InProc;
4
this._integratedSecurity = base.ConvertValueToIntegratedSecurity();
5
this._async = base.ConvertValueToBoolean("asynchronous processing", false);
6
this._connectionReset = base.ConvertValueToBoolean("connection reset", true);
7
this._contextConnection = base.ConvertValueToBoolean("context connection", false);
8
this._encrypt = base.ConvertValueToBoolean("encrypt", false);
9
this._enlist = base.ConvertValueToBoolean("enlist", ADP.IsWindowsNT);
10
this._mars = base.ConvertValueToBoolean("multipleactiveresultsets", false);
11
this._persistSecurityInfo = base.ConvertValueToBoolean("persist security info", false);
12
this._pooling = base.ConvertValueToBoolean("pooling", true);
13
this._replication = base.ConvertValueToBoolean("replication", false);
14
this._userInstance = base.ConvertValueToBoolean("user instance", false);
15
this._connectTimeout = base.ConvertValueToInt32("connect timeout", 15);
16
this._loadBalanceTimeout = base.ConvertValueToInt32("load balance timeout", 0);
17
this._maxPoolSize = base.ConvertValueToInt32("max pool size", 100);
18
this._minPoolSize = base.ConvertValueToInt32("min pool size", 0);
19
this._packetSize = base.ConvertValueToInt32("packet size", 0x1f40);
===============================其他代码省略========================================
181
}
182
}
这段代码很长,但是我们注意上面的第17行,这里有一个默认值100,就是说,如果你没有在connection string中指定max pool size,那么该值就是100。
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

===============================其他代码省略========================================
181

182

那么,如果我们代码中对于dbconn进行了Open,没有进行Close,conn pool就会一直增长,一直涨到100,涨到这个Max Pool Size。原因我们看下面:(Class DbConnectionPool)
1
case 2:
2
Bid.PoolerTrace("<prov.DbConnectionPool.GetConnection|RES|CPOOL> %d#, Creating new connection.\n", this.ObjectID);
3
try
4
{
5
fromTransactedPool = this.UserCreateRequest(owningObject);
6
}
7
catch
8
{
9
if (fromTransactedPool == null)
10
{
11
Interlocked.Decrement(ref this._waitCount);
12
}
13
throw;
14
}
15
注意上面的第5行,UserCreateRequest,看这个方法:
2

3

4

5

6

7

8

9

10

11

12

13

14

15


















上面写了这么多,结论就是,如果dbconn在Open之后,没有Close,那么会造成conn个数上涨,到100之后就会停下来。第101个链接的请求,是无法创建成功的。这样,db和web server很可能都是CPU很低,如0%,但是客户端的响应时间就是很长,造成性能下降。