首页 新闻 会员 周边 捐助

关于使用DataReader的一个很奇怪的问题,不应该用DataReader?

0
悬赏园豆:100 [已关闭问题] 关闭于 2012-05-02 11:10

.net读取数据集有两种方式:DataSet 和 DataReader

孰优孰劣我们暂且不论,我在做项目纯读取数据的时候选用了DataReader
首先我确认用完之后关闭了,百分百确认。 reader,connection都close了,甚至都dispose了。

但是出现一个很奇怪的问题:

在sqlserver(2000)中查看进程,有非常多的sleeping进程,直到最后打开页面,提示超时,说连接池满

错误提示:"超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小 "

1.我在连接字符串里加上了Pooling=false禁用了连接池,仍会出现上述问题,说明这些sleeping是sqlserver内部机制管理的。
2.当提示 "超时,说连接池满" 的时候,任然有很多sleeping的连接。

解决:将项目中所有使用DataReader的地方改用DataSet ,则不会再出现这个问题。

疑问:
1.为什么会出现这种情况,是否是因为DataReader本身的问题?如果是,那稍大并发的项目就不能用DataReader了。
2.有没有可能是sqlserver2000 本身的问题?
3.提示 超时,说连接池满 的时候,任然有很多sleeping的连接。 既然有空闲连接,为什么不用?

 

求各位大牛不吝指教!

 

-----------------------------------------

有博友说让贴代码,没有代码的确不好分析,但是项目中的代码是分层分散不太好贴。

我自己写了简单的测试,使用多线程模拟并发测试,也会出现上述问题。

代码如下: 

string conString = "Server=.;database=northwind;user id=reader;password=123456;";
SqlConnection con = new SqlConnection(conString);

SqlCommand cmd = new SqlCommand();
con.Open();
cmd.Connection = con;
cmd.CommandText = "select * from Customers";
cmd.CommandType = CommandType.Text;

using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
  while (reader.Read())
  {                    
      Thread.Sleep(30);
  }
  reader.Close();
  reader.Dispose();
  con.Close();
  con.Dispose();
}

 

 

问题补充:

SAFASDFSADFASDFSADFSDFS DFSADF SADF ASDF 

码农搞事情的主页 码农搞事情 | 初学一级 | 园豆:20
提问于:2012-04-20 15:23
< >
分享
所有回答(10)
0

我很像知道你的DataReader是怎么写的?  什么问题都是有原因的,很多时候你得到的结论不一样,不一定是你确定的那样。

使用的是微软官方的数据库操作类,使用的是最基础的SqlDataReader.

支持(0) 反对(0) 码农搞事情 | 园豆:20 (初学一级) | 2012-04-20 15:28
0

datareader用完之后要关闭。

超级码农 | 园豆:215 (菜鸟二级) | 2012-04-20 16:02

我百分百确定关闭了。包括Connection也关闭了,甚至都Dispose了,仍然如此。

支持(0) 反对(0) 码农搞事情 | 园豆:20 (初学一级) | 2012-04-20 16:03

@亻寸 日月 月月鸟: 

贴代码

支持(0) 反对(0) 超级码农 | 园豆:215 (菜鸟二级) | 2012-04-20 16:04

@亻寸 日月 月月鸟: 

不会啊,没发现你这代码里有问题。

支持(0) 反对(0) 超级码农 | 园豆:215 (菜鸟二级) | 2012-04-20 16:06
0

我之前也遇到了这样的情况,后来就再也没用过DataReader,代码看起来真的没什么问题,打开,关闭都正常,单只有一个或两个用户操作时没问题,但用户多了以后,就出现这两种情况:1.DataReader关闭  2.连接超时;到现在也没明白是怎么回事。。。期待高手解答。。。

KivenRo | 园豆:1734 (小虾三级) | 2012-04-20 16:28
0

建议楼主把下面的代码去掉,因为使用Using没必要手动释放,con.Close()应该写在Using外面,而且cmd也要释放。

    reader.Close();
  reader.Dispose();
  con.Close();
  con.Dispose();

tf.li | 园豆:202 (菜鸟二级) | 2012-04-20 16:55
0
SqlDataReader是持久性连接,读取数据会一直保持数据库连接状态。建议你把con.Close()放在using外关闭,并且有可能是同时访问量人数超出数据库连接池最大限制造成的。看下这个对你有用没?http://topic.csdn.net/u/20100421/15/c308f282-c2e4-409e-889a-95d08fb43568.html,还有这个http://blog.csdn.net/lee576/article/details/2116360
lonely_rain | 园豆:752 (小虾三级) | 2012-04-20 17:30
0
string conString = "Server=.;database=northwind;user id=reader;password=123456;";
using (SqlConnection con = new SqlConnection(conString))
{
  
SqlCommand cmd = new SqlCommand();
con.Open();
cmd.Connection = con;
cmd.CommandText = "select * from Customers";
cmd.CommandType = CommandType.Text;

SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (reader.Read())
  {                    
      Thread.Sleep(30);
  }
  reader.Close();
  reader.Dispose();
  con.Close();
}

改成这样再试试看?

I,Robot | 园豆:9783 (大侠五级) | 2012-04-22 23:47
0

1.怎么会,想要性能好一点,数据库连接是即用即关。使用连接的时间也应该尽量短。Reader是要保持连接的,不用维护DataSet的相对较大的内存开销。DataSet是一次性取回的,与连接无关。这个随便哪个文档都应该说的很清楚的。因此DataReader和DataSet应该各有各用到的地方。2.Sql2000本身没问题。3.那个Sleeping的连接也不一定是连接池能够掌握的。

你可以将连接的打开和关闭写入日志,然后再看看。您的程序的问题可能是1,没有将使用连接的时间保持在尽量短,2. 没有分层,导致出现许多不必要的数据库存取操作,加重了数据库的负担。

ChatinCode | 园豆:2272 (老鸟四级) | 2012-04-23 12:15
0

.net sql的连接池是隐式管理的。是针对连接字符串建立的连接池。你即使关了连接也只是业务上的关闭,对连接池没有影响的。

中文代码 | 园豆:951 (小虾三级) | 2012-04-24 08:26
0

楼主把using 去掉呢。

 

codeyuyu | 园豆:224 (菜鸟二级) | 2012-04-24 17:10
0

首先,DataReader本身没有任何问题

DataSet也是由DataReader灌入的。

关键在于你用DataReader读取时,不能有耗时操作!!!

while (reader.Read())
  {                    
      Thread.Sleep(30);//这里不能有逻辑操作,应该直接赋值就走(100条数据就3秒啊!!!这可不是小数目,查出来灌到dataset中都不会这么久)
  }
其次,连接池的连接关闭后是不会立即被其他线程启用的。
你可以这样试试:
构建一个command,
循环执行一个简单的update语句,
每次执行完之后重新实例化Connection

然后你检测sql会发现,新建了很多连接。。

why? 就是因为连接池本身的逻辑处理是有一定耗时的,不能保证刚关闭的connection会立即被启用

不过我不明白你怎么会有那么多的并发访问,
要知道一个页面不太可能在几毫秒内被调用多次(除非taobao之类的)
所以你要测试的话,应该是按照吞吐量,每分钟发多少次请求测试,而不是秒级的测试
lsjwzh | 园豆:113 (初学一级) | 2012-12-05 12:59
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册