2013-07-05 19 views
0

我有一個Java應用程序,其中15個線程通過名爲getNext()的同步方法從包含11,000條記錄的表中選擇一行,線程在選擇行時變慢,多少時間。每個線程遵循以下過程:從數據庫優化的多線程選擇行

  1. 線程檢查是否存在具有恢復列值設置爲1的行。

    答:如果它存在,線程將獲取該行的id並使用該id來選擇id大於獲取id的另一行。

    B.否則,它選擇與ID的行大於0

  2. 根據在上述1所述的步驟的結果接收到的最後一行被標記設置爲1。

  3. 恢復柱

    線程獲取行數據並對其進行處理。

問:

  1. 如何多線程訪問thesame表中選擇行另一個線程沒有選擇和快?
  2. 在任何線程選擇的最後一行發生崩潰的情況下,如何恢復線程?

回答

1

1 .: 看來getNext()中的多個數據庫操作是瓶頸。如果數據未被外部源更改,則可以讀取所有行的「id」和「resume」並將其緩存。比你只有一個查詢,而不是僅僅在內存中操作讀取。這將在getNext()中安全地進行大量昂貴的數據庫調用:

2 .: 基本上,您需要某種事務或至少添加一個其他列,當線程完成處理該行時,該列會被更新。基本上,處理和更新需要在單個事務中進行。當事務未完成時發生某些事情時,可以回滾到未處理該行的狀態。

1

如果線程都在同一臺機器上,他們可以使用共享數據結構來避免同步而不是同步。但是,以下假定線程在不同的計算機上(可能是應用程序服務器羣集的不同成員)開啓,並且只能通過數據庫進行通信。

刪除getNext()方法的同步。將恢復標誌設置爲1(步驟2)時,請以原子方式進行。更新表設置resume = 1,其中resume = 0,提交。只有一個線程會成功,這個線程會獲得這個工作單元。同時,設置一個恢復時間 - 如果恢復時間大於某個最大值,假定該工作單元的線程散列崩潰,則將恢復標誌恢復爲0.工作完成後,將恢復時間設置爲空,或以其他方式將工作標記爲完成。

1

好了,就想到這裏不同的問題:

  1. 你保持你的DB狀態?我會尋找一些方法,您可以調用select for update來通過非活動狀態進行過濾(確保僅在select中獲得一行)並立即更新爲active(在同一事務中)。很高興知道你在使用哪個數據庫,不知道是否選擇「更新」總是一個選項。

  2. 過程和完成時更新到完成狀態。

  3. 請務必在表中保留一個時間戳以標識上次更改狀態的時間。讓自己決定何時將活動線程視爲丟失。

  4. 定義其他可能的錯誤場景(如果進程失敗會發生什麼情況)。

您還需要分析場景。你的桌子有多少行?多少個線程同時調用它?在給定的時間內插入了多少次?根據這個你將不得不看數據庫性能如何運行。

我假設找你GETNEXT()是同步的,與我在第1點中寫道,你可能會解決這個...

+0

我使用MySQL – John

+0

下面是這個MySQL的方法:HTTP: //dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html – Martin

+0

現在,您將不得不關閉自動提交功能,並運行select for update(或在共享模式下選擇鎖定),具體取決於根據你的需求,並且直接更新狀態,以便其他線程不能接受並執行提交。 – Martin