测试在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:
- public class TestPO {
- String id;
- String name;
- int num;
- ....
- }
- <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>
- 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() throws Exception {
- TheadtestTemplate template = new TheadtestTemplate();
- template.execute(new TheadtestCallback() {
- public void doInThead(int suquence) {
- // theadTestManager.testSave(suquence);
- theadTestManager.testSaveByJdbc(suquence);
- }
- }, 10);
- }
http://www.blogjava.net/ronghao 荣浩原创,转载请注明出处:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。