blackcolor(blackcolor),因为我对COM不熟悉,以后我会慢慢看你的原创文章。连接池我会参考楼下ntr所描述的方法才是看看,因为在测试中发现,如果所有的线程共享一个ADO连接,就会出现错误:“连接占线导致另一个命令”,来源是“OLE DB Provider for Sql server”。
另外,问一个问题啊,我写了一个非常简单的StoreProcdure,里面的语句可以单独执行,整个StoreProcdure没有任何效果,语句如下:CREATE PROCEDURE dbo.restorepatient @patid char(50) , @Volume varchar(100), @LocalPath varchar(200) AS BEGIN --update 'volume' field of Series table update Series set Series.Volume=@Volume from Series INNER JOIN Image ON Series.SeriesID=Image.SeriesID where Image.ImageName like @patid and Image.LocalPath like '%_TMP' --update 'Volume' and 'LocalPath' fields of Images table update Image set Image.Volume=@Volume ,Image.LocalPath=@LocalPath from Image where Image.ImageName like @patid and Image.LocalPath like '%_TMP' END GO对于这种情况,通常是因为什么原因引起的呢? exec restorepatient @patid='02-8171%',@Volume='MR_GEMS8610_disk3',@LocalPath='c:\dicom\MR_GEMS8610_disk2' go执行后的结果:(所影响的行数为 0 行)
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.
通过大家的指导,我已经初步弄明白了问题所在。 1。关于连接失败的问题,估计是OLE DB Resource Pooling运用不当造成的, 如果大家有兴趣,可以参阅MSSDK中的一篇文档”Pooling in the Microsoft Data Access Components“,写的非常清楚,详细介绍了连接池的实现、运用等。基本正如ntr、jorry所言,在此谢过两位高手了。 2。事务死锁的问题,除了更改自己的操作流程,数据处理逻辑之外,好像没有其他的有效办法。 就此揭帖吧。
1。我也认为是因为事务死锁的原因,导致连接失败。但是这个死锁是因为同一个进程的多线程间竞争资源导致的?还是多个进程间的不同权限数据库操作,比如查询、更新、删除等导致的?还是不同数据库用户登录之后访问同一表格导致的?我一直找不到具体的理由。
2。你的回复我看不太明白,Session到底是一个什么概念呢?“连接最好不要放到Session和Application中去,这样在访问人数多的时候容易死锁,ADO不是线程共享的,如果ADO连接放到Session和Application中,连接一直不能被释放,而总的连接数是固定的,其他的程序就一直等待连接的释放,从而导致请求的队列越来越长。”
连接不放入应用程序中,那我将其放入何处呢?
需要使用ADO,时就从这些连接里取一个,用完了再放回去(实际上就是自己
实现连接池而已)
至于死锁问题,可以检查,
1)是不是在用户进行数据输入时,就启动了一个事务
2)是不是启动了事务一直没提交
建立一个进程共享区,当用户请求连接并在查询完成要释放连接时,不关闭此连接,而是把这个连接放到共享区中。下一个用户请求查询时,先从共享区找有无可用连接,如果有,使用该连接查询,如无,则新建一个,使用完毕后同样放入共享区。
这样带来的问题:
1、共享区里的连接要做保护,以免不同进程同时使用一个连接;
2、要限制共享区连接的数目,以免资源耗尽;
3、要写一个查询可用连接的算法。仅供参考,希望对楼主有所帮助。
你说的关于共享连接池的做法,应该是完全可以的,但是这里涉及了Aizz所说的几个问题,必须解决这些问题,才能很好的建立连接池。难道旧贴中各位高手谈到的“连接池”就是这个意思吗?需要自己维护、管理连接?目前我的做法是将一个连接作为全局变量来实现,每个线程都共享这个数据库连接(这里是不是要考虑ADO是否线程安全的问题呢?必须经过实践得知。)另外,你所说的死锁问题如何检测呢?通过“事件探查器”吗?
因为我所用到的仅是一些Update、Select、Insert语句,所以事务的概念是ADO自身为我建立、提交的,所以这里应该不是因为事务没有提交而导致的,另外a.exe是一个服务程序,没有与用户进行交互。
另外,如果HR的值转换为16进制之后,是0x80004005的话,这个代表什么意思啊?在MSDN中我一直没有找到响应的错误解释,还望老兄明示啊。
另外,我认为ADO是线程安全的。起码我的程序到现在还没有出现过问题。
我所了解的资料中,连接池是com+的特性,
请参考我以前所写的关于COM的一些文章
http://www.csdn.net/develop/read_article.asp?id=9512
另外,就算是自己管理ADO的连接池,也不是特别复杂
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以上。
1。我已经建立了一个全局连接,但是多线程共享使用出现了错误,所以此方法不妥啊,不过看了你的描述,我必须在每个线程中再次建立临时连接对象,然后在使用它。这里有一个问题,就是对于临时对象的管理问题,我必须使用_ConnectionPtr.Release来释放COM控件实例吗?还是仅仅调用Close关闭连接就可以了?
2。关于死锁的问题,对于SQL Server中的锁机制,应该是仅作用于数据库的对象,比如表、库、表中的记录等。所以无论是单个进程中的多个线程开启的多个连接,还是多个进程不同数据库用户登录后开启的多个连接,都是一样的,即锁机制与线程、进程无关,仅于数据库对象有关,不知道我的理解对不对?望你明示啊。我的应用中大部分都是SQL语句,不过也利用了Recordset处理Select语句返回的结果,但是我自己应用程序中的Select、Update等语句我可以协调,但是别的进程,比如IIS通过ASP访问数据库的同一表格,这时我就无能为力了,数据库应该协调访问操作吧?
3。关于_ConnectionPrt.Open返回的HRESULT不等于S_OK,你的意思是我的程序中没有必要判断FAILED(HR),因为_ConnectionPtr自身会抛出异常?
4。如何明确知道MDAC的版本呢?
期待你的回复。
2. 锁机制由数据库提供无需应用程序实现,应用程序的线程和数据库线程也不同。数据库当然会协调锁机制,不管是那个应用程序的那个线程。死锁的关键是事务的过程中可能对不同的资源先后要进行加锁造成的冲突。如果你有BeginTrans等事务语句不妨先注释,看看是不是这个原因。
3. 对,如果ADO的版本没问题,应该能抛出异常的。你可以看msado15.tli中的源程序。
4. 看C:\Program Files\Common Files\System\ado下的msado15.dll的版本。(操作系统在C盘)
第一:必须用完全同样的连接字符串
第二:用完connection对象后,尽量快的调用close()关闭它,在vb,vbscript里也要显式的调用close()
这样ado会自动把连接放入池中,直到超时或应用程序关闭。com+里的pooling和ado的pooling基本上是不相干的,只有当com+对象池中某对象被完全清除时,和此对象联系的ado连接池中的连接也会清空。ado.net中连接池和ado中基本相同,只不过你可以明确的选择不使用连接池机制。
@patid char(50) ,
@Volume varchar(100),
@LocalPath varchar(200)
AS
BEGIN
--update 'volume' field of Series table
update Series
set Series.Volume=@Volume
from Series INNER JOIN Image ON Series.SeriesID=Image.SeriesID
where Image.ImageName like @patid and Image.LocalPath like '%_TMP' --update 'Volume' and 'LocalPath' fields of Images table
update Image
set Image.Volume=@Volume ,Image.LocalPath=@LocalPath
from Image
where Image.ImageName like @patid and Image.LocalPath like '%_TMP'
END
GO对于这种情况,通常是因为什么原因引起的呢?
exec restorepatient @patid='02-8171%',@Volume='MR_GEMS8610_disk3',@LocalPath='c:\dicom\MR_GEMS8610_disk2'
go执行后的结果:(所影响的行数为 0 行)
1。你对楼上的ntr做的回复,“MSDN的资料显示,连接池应该有至少一个常驻的连接存在才会起作用,所以应该创建一个全局的连接并打开它。然后,在应用程序中创建每次可用的临时连接对象,再使用它。”,有何理解和认识呢?
2。说到隐含连接,本站上有一片zhengyun_ustc写的一篇文章,
http://www.csdn.net/develop/read_article.asp?id=15591
你看看是不是有同感?但是MSDN中关于此问题的描述还是比较少的。
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 );
}
CREATE PROCEDURE dbo.restorepatient
@patid char(50) ,
@Volume varchar(100),
@LocalPath varchar(200)
AS
更改为
CREATE PROCEDURE dbo.restorepatient
@patid varchar(50) ,--使用中发现的
@Volume varchar(100),
@LocalPath varchar(200)
AS
1。前面关于错误的处理我知道,因为msado.tli中就是这么处理的,并且我所使用的ADO类中也是这么处理异常的,一旦报告“未定义错误”,就不知道该怎么办了。
2。存储过程的问题解决了,数据类型导致执行没有效果,原来SQL Server对数据的长度有限制,必须把char改为varchar才行。但是MSDN中没有找到相关的解释。
回复人: seth99(seth) ( ) 信誉:100 2002-12-11 0:08:57 得分:0 死锁与登录用户没有关系,关键是看你有多少个连接在同时读写数据,100万,如果不是很复杂的系统或者很糟糕的程序,应该不会很容易出现死锁,如果确实更新很频繁,可以在程序中作处理,例如可以根据需要降低锁定等级,采用batch update,锁定判断等处理避免循环锁就好了,另外不在一个表里放超过1个image字段也可以避免一些不必要的锁定.
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.
http://www.sql-server-performance.com/bl_asp_ado.asphttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmdac/html/pooling2.asphttp://support.microsoft.com/default.aspx?scid=KB;en-us;q191572
1。关于连接失败的问题,估计是OLE DB Resource Pooling运用不当造成的,
如果大家有兴趣,可以参阅MSSDK中的一篇文档”Pooling in the Microsoft Data Access Components“,写的非常清楚,详细介绍了连接池的实现、运用等。基本正如ntr、jorry所言,在此谢过两位高手了。
2。事务死锁的问题,除了更改自己的操作流程,数据处理逻辑之外,好像没有其他的有效办法。
就此揭帖吧。