首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

[Hibernae+Spring]压力测试所唤起的死锁和无法同步

2012-11-18 
[Hibernae+Spring]压力测试所引起的死锁和无法同步?项目在压力测试中有个业务流程无法通过50个用户同时并

[Hibernae+Spring]压力测试所引起的死锁和无法同步?
项目在压力测试中有个业务流程无法通过50个用户同时并发,初步认为是由于一个实体类无法和数据库同步而失败。这个实体类是下面错误信息中的SysBillManage。
首先简单的说明一下SysBillManage,它的功能是根据传递参数分配单据号,并且实现自增。比如是出库通知单,那么参数是OUT_DO_INFORM_ORDER,那么得到的结果是OutB0000001这样的形式的单据号,每一次增加出库通知单则单据号增1,既是OutB0000002。其中参数OUT_DO_INFORM_ORDER对应于数据库SysBillManage表中的一条记录的ID。
在用silkperformer 6.5做压力测试的时候,则出现一下异常,测试用例就是并发生成出库通知单:




请各位大大看看到底是哪里出了问题 public void update(SysBillManage persistentInstance) { log.debug("deleting SysBillManage instance"); try { getHibernateTemplate().update(persistentInstance); getHibernateTemplate().flush(); log.debug("delete successful"); } catch (RuntimeException re) { log.error("delete failed", re); throw re; } }

并发情况下,首先是某用户A取得单据号001,然后将sysBillMange update,执行getHibernateTemplate().update(persistentInstance);这个方法。此时getOrderNO这个方法结束,同步完成,下一个用户B进入方法,执行get取得单据号的操作,但是这个时候,用户A的update动作还未真正写入数据库,此时用户B取得的还是001而不是002。所以就出错了,所以我尝试着将它立即写入数据库,系统压力测试就正常了。
其他代码都没有在执行动作之后立即flush,系统瓶颈在这里,所有操作都要涉及到这个表,虽然这种写法比较慢……
spring的配置应该保证了事务的原子性,但是还是出现这样的事务问题,到底是为什么呢?难道是粒度问题?
事务A开始
{
事务B...
}事务A结束
难道是保证了事务A而在事务A中的事务B(既是这里的取得更新单据号)没有保证?

引用
象你这个需求,从实现方式上面就已经形成了一个瓶颈,所有的操作都集中在一个表上,要在上面取ID,并发的时候出现deadlock或者取出同一个id就是必然了,建议采用缓冲的机制,对于每个用户,他每次到ID表中取的ID的时候,都是取回一批ID,另外一个session来取得时候,拿到的是另外一批,然后这个用户在生成ID的时候,从这个缓冲中取,取尽的时候才重新去表中得到另外一批ID。

缓存是一个很好的方案,hibernate的缓存机制还没用上,找个时间研究下。^^ 9 楼 lzzzl 2007-02-09   Readonly 写道string类型PK改到数字类型PK只能减少page lock,但是不能消除。
根本的解决方法是改序列号生成方法,像你这种在一个表里面记录最大值,然后不停累加,然后再更新到其他表,很容易出deadlock。
你可以将这个最大值在系统启动的时候从各个表读取,然后更新,并且把这个值放到内存中,这样在系统运行中的时候就不需要和这个表打交道了。

这里有一些其他技巧减少lock的资料,也可以参考一下:
http://www.sql-server-performance.com/reducing_locks.asp

请问为什么INT类型的PK比STRING类型引发的死锁要少呢? 10 楼 denghan 2007-03-31   50个用户同时并发
------------------
请教楼主用什么测试软件可以实现50个用户的并发访问?可以告诉个软件名称吗?
非常感谢~!

热点排行