我目前遇到Spring Hibernate的竞争问题(通过服务和daoImpl类的注释进行事务处理)。这是我遇到的:
表:
注意device_identifier和device_type_id是唯一唯一的
以下是我在多线程进程中所拥有的代码片段:
if(deviceDao.findByIdentifierAndTypeId(identifier, typeId) == null){
Device newDevice = new Device();
newDevice.setIdentifier(identifier);
newDevice.setTypeId(typeId);
deviceDao.add(newDevice);
}
所以会发生的是,我有一个通过websockets监听设备的服务器(这里可能不是重要的细节),服务器首先会尝试确定设备是否已经在数据库中,如果没有,则创建设备记录已经找到了。
现在我遇到的问题是服务器可以处理来自设备的多条消息(根据设备的每条消息创建一个线程),从而处理竞争条件。
想象一下:
设备A一个接一个地发送两条消息:
Sends hello message Sends "here is my ip" message
| |
| |
| |
does not see device in DB |
tries to insert does not see device in DB
| tries to insert
Insert completed |
Failed to insert (Unique key constraints not met)
显然,当第二次插入设备时,唯一约束将导致失败。但我在想,当第一个插入完成后,Spring就可以把它拿起来,并且知道当第二个线程再次尝试插入时它就不需要了。但是,尽管我尝试了各种Propogation和Isolation模式,但这并没有发生。我必须遗漏一些非常基本的东西,请指出我如何解决这个问题的正确方向。提前感谢您的回复。如果需要/我要求,我会提供更多信息。
答案 0 :(得分:1)
这是设计行为。默认情况下,您只会看到已提交的行(READ COMMITTED隔离级别)。对于外部进程,您可以将未提交的行视为尚未出现在数据库中。
最佳解决方案是捕获唯一约束违规并重试(理想情况下是延迟)。您也可以将隔离级别设置为读取未提交,但这可能会创建其他竞争条件,我不建议这样做。