读书人

高并发下死锁有关问题分析好久想不明

发布时间: 2014-01-09 23:07:34 作者: rapoo

高并发下死锁问题,分析好久想不明白
开发了日报功能,在做压力测试的时候,新建的时候报死锁,调试了好久,不明白产生的原因。

通过日志发现,这些并发可以穿插执行,但是新增和删除不是会加意向排他锁,在事务没提交结束前,其他线程怎么能会都执行到
this.eventTagService.save(event, tags);

看日志,死锁都是在建立关系的时候发生的,望各位指点下!先谢啦!



业务场景:用户填写一条日程数据,包括日程内容和一些标签,日程内容放在记录表A上,标签都在一张信息表B上,无重复

表:A表 B表 AB表(关联表)

代码逻辑
1、数据插入表A

2、迭代标签,查找B表,如果有返则回数据,无则插入后返回

3、在AB表插入数据,建立关联


结果在压力测试的时候,发现有死锁
报错:
org.hibernate.exception.LockAcquisitionException


2013-12-24 17:00:00 [http-8888-14:3236837] - [WARN] SQL Error: 1213, SQLState: 40001
2013-12-24 17:00:00 [http-8888-14:3236837] - [ERROR] Deadlock found when trying to get lock; try restarting transaction



用的注解事务,数据库是mysql
代码:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public Event save(Event event) {
try {
logger.info(Thread.currentThread().getName()+":日志新增开始");
if (event.getId() == null) {

this.fillForSave(event);

}

logger.info(Thread.currentThread().getName()+":event开始--新增");
this.eventDao.save(event);
logger.info(Thread.currentThread().getName()+":event结束--新增");


this.follow(event);
logger.info(Thread.currentThread().getName()+":日志新增结束");
return event;
} catch (Exception e) {
e.printStackTrace();
logger.error(Thread.currentThread().getName()+e.getMessage());
return null;
}
}



private void follow(Event event){
logger.info(Thread.currentThread().getName()+":tags开始");
List<Tag> tags = this.tagService.saveTags(event.getClassifications(), TagType.Normal);
logger.info(Thread.currentThread().getName()+":tags结束");

if(tags==null || tags.size()==0){
tags = new ArrayList<Tag>();
tags.add(this.tagService.saveTag("默认", TagType.Normal));
}

if (event.getProjectId() != null && event.getProjectId() != -1) {
tags.add(this.tagService.saveTag(event.getProjectName(), TagType.Project));
tags.add(this.tagService.saveTag(event.getWorkTypeName(), TagType.JobType));
}

logger.info(Thread.currentThread().getName()+":关系开始");
this.eventTagService.save(event, tags);
logger.info(Thread.currentThread().getName()+":关系结束");

this.attentionService.eventUpdate(event.getCreator());
}



@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public List<EventTag> save(Event event, List<Tag> tags) {
//保存之前,删除旧的
logger.info(Thread.currentThread().getName()+":删除关系开始");
this.deleteEventTagByEventId(event.getId());
logger.info(Thread.currentThread().getName()+":删除关系结束");


//this.eventTagDao.flush();
//保存新的
logger.info(Thread.currentThread().getName()+":建立关系开始");
List<EventTag> eventTags = new ArrayList<EventTag>();
if(tags != null && tags.size() != 0) {
for(Tag tag : tags) {
EventTag eventTag = new EventTag(event, tag);
this.eventTagDao.save(eventTag);
logger.info(Thread.currentThread().getName()+":建立关系");
eventTags.add(eventTag);
}
}
logger.info(Thread.currentThread().getName()+":建立关系结束");
return eventTags;
}




@Override
public Tag saveTag(String tagName, TagType tagType) {
Tag tag = this.get(tagName, tagType);

if(tag == null) {
tag = new Tag(tagName, tagType);
this.tagDao.save(tag);
}

return tag;
}


/**
* 批量保存标签
*/
@Override
public List<Tag> saveTags(String tagNames, TagType tagType) {
List<String> names = TagUtils.convert(tagNames);
List<Tag> tags = new ArrayList<Tag>();
if(names == null || names.size() == 0) {
return tags;
} else {
for(String name : names) {
Tag tag = this.saveTag(name, tagType);
tags.add(tag);
}
return tags;
}
}





[解决办法]
涉及到线程安全的问题了。sychronized 解决
[解决办法]
这个建议采用存储过程执行,
func_**
begin
lock table ** in exclusive mode;
do
end
这样多线程是能确保正常

读书人网 >J2EE开发

热点推荐