关于多线程共享ADO连接的问题?

各位高手,请看:
我本来利用了老外封装的一个ADO类(http://www.codetools.com/database/caaadoclass1.asp,有兴趣的可以去看看,使用还是非常方便的)开发了一个多线程的网络服务程序a.exe,(因为听说ADO不是线程安全的,所以认为多线程不能共享连接,不知道认识是否错误?)现在的运行方式是处理一个客户请求开启一个线程,每个线程都会打开一个数据库连接,(线程运行结束的时候,就会关闭连接)。开始运行较为稳定,运行一两天之后,打开连接就失败了,重起服务程序之后,就可以连接成功。另外,该服务程序a.exe需要查询、插入、更新数据库中的表,同时另一个程序b.exe需要更新同样的表,web服务器也要通过ASP查询、插入这些表。问题如下:
1)导致连接失败的原因是什么呢?打开的连接太多?(最多的时候a.exe有六个线程同时运行,但是他们会频繁的打开、关闭连接)。听别人说“连接池”可以解决打开连接太多的带来的问题,哪位高手解释一下“连接池”如何实现?
2)b.exe在更新表中的记录的时候,出现错误,大意如下:”0x80004005错误,spid 65作为事务死锁的牺牲品,被禁止了,请重新运行事务”,是不是进程间访问数据库互斥操作导致的?如何解决呢?a.exe和b.exe采用不同的数据库用户登录,也不行。事务死锁会不会导致连接失败呢?
3)DB Connection 和 Session有何不同?二者的关系是什么呢?如何共享Connection呢?如何ADO编程实现?

我已经查阅了很多资料,一直没能解决问题,请各位高手指点几句。
因为我是新手初来查到,分数有限,等有分了,再加分。
---------------------------------------------------------------

1、导致连接失败的原因应该是死锁,这时很多进程都在等待其他的进程释放连接,如果死锁,肯定导致连接失败

3、连接最好不要放到Session和Application中去,这样在访问人数多的时候容易死锁,ADO不是线程共享的,如果ADO连接放到Session和Application中,连接一直不能被释放,而总的连接数是固定的,其他的程序就一直等待连接的释放,从而导致请求的队列越来越长。。。。
---------------------------------------------------------------

---------------------------------------------------------------
用FAILED(hr)里hr的值转成16进制,然后在MSDN里面搜索这个值就可以得到错误码。

共享Connection或者可以这样:
建立一个进程共享区,当用户请求连接并在查询完成要释放连接时,不关闭此连接,而是把这个连接放到共享区中。下一个用户请求查询时,先从共享区找有无可用连接,如果有,使用该连接查询,如无,则新建一个,使用完毕后同样放入共享区。
这样带来的问题:
1、共享区里的连接要做保护,以免不同进程同时使用一个连接;
2、要限制共享区连接的数目,以免资源耗尽;
3、要写一个查询可用连接的算法。

仅供参考,希望对楼主有所帮助。
---------------------------------------------------------------

1. ADO连接池其实就是OLEDB连接池,是存在的。不过,MSDN的资料显示,连接池应该有至少一个常驻的连接存在才会起作用,所以应该创建一个全局的连接并打开它。然后,在应用程序中创建每次可用的临时连接对象,再使用它。全局对象在程序退出释放,但并不使用。你可以测试这样做的效率和共享一个连接对象的效率。
2. 死锁的原因是因为事务中加锁的顺序。如果都是隐式的事务即单条SQL语句基本不会造成死锁。显式事务和游标操作即recordset的movenext等,会造成死锁,要分析事务的加锁过程,更新锁、只读锁、独占锁等的次序问题。如果事务的开始就是独占锁或更新锁大多数情况不会死锁。
3. COM的智能指针_ConnectionPtr已经封装了异常机制不需要FAILED(HRESULT),源程序if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
4. _ConnectionPtr.Close是关闭连接但不是释放COM对象,释放对象要_ConnectionPtr.Release()。
5. ADO的程序注意MDAC的版本,最好2.6以上。
---------------------------------------------------------------

pooling是ado自己实现的,对开发者是透明的,不过要想充分利用ado的pooling机制,需要注意几点问题
第一:必须用完全同样的连接字符串
第二:用完connection对象后,尽量快的调用close()关闭它,在vb,vbscript里也要显式的调用close()
这样ado会自动把连接放入池中,直到超时或应用程序关闭。

com+里的pooling和ado的pooling基本上是不相干的,只有当com+对象池中某对象被完全清除时,和此对象联系的ado连接池中的连接也会清空。

ado.net中连接池和ado中基本相同,只不过你可以明确的选择不使用连接池机制。
---------------------------------------------------------------

回答简单的
catch(_com_error &e)
{
CString ErrorStr;
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
ErrorStr.Format( "Error\n\tCode = %08lx\n\tCode meaning = %s\n\tSource = %s\n\tDescription = %s\n",
e.Error(), e.ErrorMessage(), (LPCSTR)bstrSource, (LPCSTR)bstrDescription );
AfxMessageBox( ErrorStr, MB_OK ¦ MB_ICONERROR );
}
---------------------------------------------------------------

maybe helpful
Q. If I use only one Connection object, does that mean I'll have only one connection to my database?

A. No. If you ask ADO to accomplish a task and ADO determines that it cannot perform that task because the connection is busy, it will establish a temporary connection to your database in order to complete the task. This behavior is most likely to affect developers using SQL Server who encounter the limitation of one active query per connection. We'll talk about this more in Chapter 7 when we discuss cursors, but keep that distinction in the back of your mind. One Connection object does not equal one connection to your database.

Published At
Categories with 数据库类
Tagged with
comments powered by Disqus