如何在这种并发情况下确保数据一致性?

时间:2010-03-12 13:09:57

标签: java mysql concurrency data-consistency

问题在于:

  • 我有多个需要访问一个数据库表的竞争线程(100+)
  • 每个线程将传递一个String name - 表中存在该名称,数据库应返回该行的id,该名称尚不存在,应插入名称并返回id
  • 数据库中只能有一个name实例 - 即。名称必须是唯一的

如何确保线程1不会在线程2尝试插入name1的同时插入name1?换句话说,我如何保证并发环境中name的唯一性?这也需要尽可能高效 - 这有可能成为一个严重的瓶颈。

我正在使用MySQL和Java。

由于

3 个答案:

答案 0 :(得分:7)

假设name列有唯一约束,每个insert将获得一个锁。任何尝试同时插入第二次的线程将等到第一个insert成功或失败(tx提交或回滚)。

如果第一个事务成功,则第二个事务将因唯一键冲突而失败。然后你知道它已经存在了。

如果每个交易有一个插入,那么它就是。如果每个事务有多个插入,则可能会死锁。

  

每个线程都会传递一个String名称 -   表中存在该名称的位置,   数据库应该返回id   行,名称不是   已存在,名称应该是   插入并返回id。

总而言之,算法是这样的:

1 read row with name
   2.1 if found, return row id
   2.2 if not found, attempt to insert
      2.2.1 if insert succeeds, return new row id
      2.2.2 if insert fails with unique constraint violation
          2.2.2.1 read row with name
          2.2.2.2 read should succeed this time, so return row id

由于唯一索引上可能存在高权限,因此insert可能会阻止一段时间。在这种情况下,交易可能超时。进行一些压力测试,并调整配置,直到它与您的负载正常工作。

此外,您应该检查是否出现唯一约束违规异常或其他一些异常。

同样,这只适用于每个事务有一个插入,否则它可能死锁


此外,您可以尝试使用“select * for update”读取第1步中的行。在这种情况下,它会等待并发插入提交或成功。由于对索引的争用,这可以略微减少步骤2.2.2中的错误量。

答案 1 :(得分:3)

在数据库中的名称列上创建唯一约束。

答案 2 :(得分:2)

为名称列添加唯一约束。

相关问题