Spring休眠插入竞争条件

问题描述 投票:2回答:1

我目前在Spring Hibernate中遇到种族问题(通过在service和daoImpl类上的注释进行事务处理)。这是我所遇到的:

表格:

  • 设备类型:ID(序列号),名称
  • 设备:ID(序列),设备标识符,设备类型ID,IP地址

注意device_identifier和device_type_id一起是唯一的

这里是我在多线程进程中的摘要:

    if(deviceDao.findByIdentifierAndTypeId(identifier, typeId) == null){
        Device newDevice = new Device();
        newDevice.setIdentifier(identifier);
        newDevice.setTypeId(typeId);
        deviceDao.add(newDevice);
    }

所以发生的事情是,我有一台服务器通过websocket侦听设备(这里可能不是很重要的细节),并且该服务器将首先尝试确定该设备是否已存在于数据库中,如果尚未创建设备记录,则会创建该记录找到。

现在,我的问题是服务器可以处理来自设备的多条消息(设备中的每条消息都会创建一个线程),因此也存在竞争状态。

想象一下:

设备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可以将其拾取并知道当第二个线程再次尝试插入时,则不需要这样做。但是,尽管我尝试了各种传播和隔离模式,但都没有发生。我必须缺少一些非常基础的东西,请向我指出如何解决此问题的正确方向。提前感谢您的回复。如果需要/要求,我将提供更多信息。

spring hibernate postgresql transactions race-condition
1个回答
2
投票

这是设计使然。默认情况下,您仅会看到已提交的行(READ COMMITTED隔离级别)。对于外部进程,可以将未提交的行视为数据库中尚不存在

最佳解决方案是捕获唯一的约束违例并重试(最好是延迟)。您还可以将隔离级别设置为“未提交”,但这可能会导致其他竞争条件,因此我不建议这样做。

© www.soinside.com 2019 - 2024. All rights reserved.