• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

sqlserver2000上在单元测试里进行多线程并发出现的死锁情况

发布: 2009-9-21 09:39 | 作者: webmaster | 来源: 本站原创 | 查看: 113次 | 进入软件测试论坛讨论

领测软件测试网

sqlserver2000上在单元测试里进行多线程并发出现的死锁情况   软件测试

测试在sqlserver2000上进行,对工作流操作的相关方法在单元测试里进行多线程并发。测试发现sqlserver出现死锁的情况相当多,一些典型的情况:

1、对同一张表先insert再update是很快会引起死锁的,不管操作的是否是同一记录

        解决方法:对于同一记录,需要调整hibernate的映射策略,使得一次insert完成操作。对于不同的记录需要在代码中手动flush,使得update先于insert。

2、对两张表进行多次update操作时,两张表交替update也会很快引起死锁

        解决方法:在代码中手动flush,保证对两张表的update不会出现交替的情况。

3、部分大范围扫描的select和update混合也会导致死锁

        解决方法:优化sql,尽量减少sql语句,通过给po增加持久化字段的方式减少关联查询

        经过优化,大部分情况下数据库死锁的情况得以避免,另外奇怪的是通过事件探查器在死锁时并未发现锁升级的事件。但是在一些特殊情况下(例如多个并发汇聚的直接联合),死锁依旧发生。最后不得不对方法进行synchronized关键字同步,这个通过synchronized flush完成。业务方法不必同步,最后批量操作数据库时进行同步。

        换oracle进行测试,在未synchronized的情况下,未发生死锁情况。由此可见sqlserver与oracle锁实现机制存在很大的差别。另,同事说,sqlserver2005性能和机制发生了很大的变化,未测试。

        补充一下我的一个最简单情况下的测试用例: PO:

view plaincopy to clipboardprint?
public class TestPO {  
 
    String id;  
 
    String name;  
 
    int num;  
 
     
 
    ....  
 

public class TestPO {

    String id;

    String name;

    int num;

  

    ....

}映射文件 hibernate3: view plaincopy to clipboardprint?
<hibernate-mapping default-access="field"> 
 
  <class table="WFMS_TESTPO" name="com.eway.workflow.test.po.TestPO"> 
 
 
 
    <id name="id" column="ID"><generator class="uuid" /></id> 
 
 
 
    <property name="name" column="NAME" type="string"/> 
 
 
 
    <property name="num" column="NUM" type="integer"/> 
 
 
 
  </class> 
 
</hibernate-mapping> 

<hibernate-mapping default-access="field">

  <class table="WFMS_TESTPO" name="com.eway.workflow.test.po.TestPO">

 

    <id name="id" column="ID"><generator class="uuid" /></id>

 

    <property name="name" column="NAME" type="string"/>

 

    <property name="num" column="NUM" type="integer"/>

 

  </class>

</hibernate-mapping>被测试方法(都配置有事务): view plaincopy to clipboardprint?
public void testSave(int num) {  
 
    TestPO po = new TestPO();  
 
    po.setName("ronghao");  
 
    po.setNum(num);  
 
    theadTestDao.save(po);  
 
    po.setName("haorong");  
 
}  
 
 
 
public void testSaveByJdbc(int num) {  
 
    String sql = "insert into WFMS_TESTPO (ID,NAME,NUM) values (?,'RONGHAO',?)";  
 
    Object[] params = new Object[]{num,num};  
 
    jdbcTemplate.update(sql, params);  
 
    sql="update WFMS_TESTPO set name='haorong' where id=?"  ;  
 
    params = new Object[]{num};  
 
    jdbcTemplate.update(sql, params);  
 

    public void testSave(int num) {

        TestPO po = new TestPO();

        po.setName("ronghao");

        po.setNum(num);

        theadTestDao.save(po);

        po.setName("haorong");

    }

 

    public void testSaveByJdbc(int num) {

        String sql = "insert into WFMS_TESTPO (ID,NAME,NUM) values (?,'RONGHAO',?)";

        Object[] params = new Object[]{num,num};

        jdbcTemplate.update(sql, params);

        sql="update WFMS_TESTPO set name='haorong' where id=?"  ;

        params = new Object[]{num};

        jdbcTemplate.update(sql, params);

    }测试用例: view plaincopy to clipboardprint?
     public void testSave() throws Exception {  
 
        TheadtestTemplate template = new TheadtestTemplate();  
 
        template.execute(new TheadtestCallback() {  
 
            public void doInThead(int suquence) {  
 
//               theadTestManager.testSave(suquence);  
 
                theadTestManager.testSaveByJdbc(suquence);  
 
            }  
 
        }, 10);  
 
    } 

     public void testSave() throws Exception {

        TheadtestTemplate template = new TheadtestTemplate();

        template.execute(new TheadtestCallback() {

            public void doInThead(int suquence) {

//               theadTestManager.testSave(suquence);

                theadTestManager.testSaveByJdbc(suquence);

            }

        }, 10);

    }

        测试结果:不论是hibernate还是jdbc,并发情况下都很快就会引起sqlserver2000的死锁,换用两种数据库驱动jtds和jturbo死锁的情况没有变化。 结论:sqlserver2000数据库的lock配置策略,不支持,或者数据库本身,就不支持对不同的行做同时操作(或者支持不完善),所谓的行锁支持很不完善,死锁情况非常容易发生。 补充:我对数据库的一些实现机制也并不是很了解,所以这里也只能列出现象而不能解释死锁的根本原因。

 

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/

TAG: 单元 死锁 线程


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备2023014753号-2
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网