用Delphi5开发MTS/COM+组件,Alpha组件的事务类型是需要事务,其中一个方法Alpha.FuncA是这样的:读取表TableA的部分数据到一个TClientDataSet中,修改或者删除其中的一些记录,并加入另外一些记录,然后保存这个TClientDataSet的Delta。后台数据库是SQLServer2000。
单独执行Alpha.Func没有问题,但是并发时会在保存Delta时发生死锁。初步理解为:当FuncA读取TableA时就对TableA加了一个共享锁,而只有保存Delta后才撤除这个共享锁。而其他用户调用FuncA时,也在读取TableA时加锁,从而在保存Delta时相互等待。请教各位大虾,这样的理解对吗?真正的原因是什么?如何解决掉类似的并发问题?通常的针对MTS/COM+并发的解决方案是怎样的?

解决方案 »

  1.   

    顶!!!
    参考:
    http://www.csdn.net/expert/topic/829/829731.xml?temp=.9648554nealzhao() ,的确是共享锁和更新锁转换时发生的。注意到COM+1.5提供了对隔离等级的属性,但是好像老的版本里没有这个属性。不可能指定用XP吧?现在的一个妥协的方法是在Alpha.FuncA的头部创建了一个SharePropertyGroupManager,使得并发时在这里排队。这样的效率肯定会受到影响,现在测试部正在测,阿弥托佛~~~我想,在一个强业务逻辑的组件里,肯定会经常发生:读取一个表,对其中的数据进行处理,然后再保存回去  这样的过程,而且往往会需要事务(,或者至少是支持事务,如果调用者具有事务,仍然使这取存的过程存在于一个事务中)。难道必定会发生这种死锁吗?有开发过COM+/MTS分布式系统的大哥大姐吗?通常对这种情况是如何处理的?或者,通常的COM+/MTS分布系统的并发性问题是如何处理的?唉,我们设计时没有对资源做规划,现在并发和强度问题多多  :(...
      

  2.   

    通常来说我总是努力减少对数据库的访问时间和次数来避免锁定。比如你所说的操作,对于这种频繁发生的操作,我使用储存过程来实现。当使用储存过程时,锁定由SQLServer来维护,只要你的储存过程中不会出现死锁就行。
    如果你的操作并不要求实时刷新数据库,则可以使用缓冲来减少写表的次数,可以进一步减少锁定的机会。
      

  3.   

    通常来说我总是努力减少对数据库的访问时间和次数来避免锁定。比如你所说的操作,对于这种频繁发生的操作,我使用储存过程来实现。当使用储存过程时,锁定由SQLServer来维护,只要你的储存过程中不会出现死锁就行。
    如果你的操作并不要求实时刷新数据库,则可以使用缓冲来减少写表的次数,可以进一步减少锁定的机会。
      

  4.   

    既然同时有多个用户同时修改一个表的需求,那么在读取数据时就不要用事务了。
    这在web方式的w/s结构中常用到。
      

  5.   

    COM+中最好别设成需要事务,我的经验是设成支持事务,然后在需要的时候自己用代码创建一个事务环境,用完再销毁之,这样可减少冲突机率,使事务可以控制。我的应用有100多人在用,没有死锁。
      

  6.   

    copy& paste from msdn
    Shared Locks
    Shared (S) locks allow concurrent transactions to read (SELECT) a resource. No other transactions can modify the data while shared (S) locks exist on the resource. Shared (S) locks on a resource are released as soon as the data has been read, unless the transaction isolation level is set to repeatable read or higher, or a locking hint is used to retain the shared (S) locks for the duration of the transaction.
      

  7.   

    To All:  我觉得不是事物粒度的问题,只要这个组件是强业务逻辑的,必定会发生这种情况。除非组件不带逻辑,仅仅进行存取操作。后来我们的解决方案是 在读取表之前,“Set Transaction Isolation Level Read Committed”,在读取表之后,“Set Transaction Isolation Level Serializable”.谢谢各位指点,明天晚上结帖  ;)