簡體   English   中英

如何在這種並發情況下確保數據一致性?

[英]How do I ensure data consistency in this concurrent situation?

問題是這樣的:

  • 我有多個需要訪問一個數據庫表的競爭線程(100+)
  • 每個線程都將傳遞一個String name - 該名稱存在於表中,數據庫應返回該行的id,該名稱尚不存在,應插入名稱並返回id。
  • 數據庫中只能有一個name實例 - 即。 名稱必須是唯一的

如何確保線程1不會同時插入name1 ,因為線程2也嘗試插入name1 換句話說,如何保證並發環境中name的唯一性? 這也需要盡可能高效 - 這有可能成為一個嚴重的瓶頸。

我正在使用MySQL和Java。

謝謝

假設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中的錯誤量。

在數據庫中的名稱列上創建唯一約束。

為name列添加唯一約束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM