2013-02-05 40 views
1

我有一個表「鏈接」與一些下載鏈接。PostgreSQL鎖表

我的.NET應用程序讀取此表,獲取鏈接,創建Web客戶端並下載關聯的文件。 我想要創建幾個線程來完成這個任務,但是每個線程都應該讀取一個不同的記錄,否則兩個線程會嘗試下載同一個文件。 這怎麼辦?

我都試過,但它不工作:

public static Boolean Get_NextProcessingVideo(ref Int32 idVideo, ref String youtubeId, ref String title) 
    { 
     Boolean result = false; 

     using (NpgsqlConnection conn = new NpgsqlConnection(ConfigurationDB.GetInstance().ConnectionString)) 
     { 
      conn.Open(); 
      NpgsqlTransaction transaction = conn.BeginTransaction(); 

      String query = "BEGIN WORK; LOCK TABLE links IN ACCESS EXCLUSIVE MODE; SELECT v.idlink, v.title " + 
       " FROM video v WHERE v.schedulingflag IS FALSE AND v.errorflag IS FALSE ORDER BY v.idvideo LIMIT 1; " + 
       " COMMIT WORK;"; 
      NpgsqlCommand cmd = new NpgsqlCommand(query, conn, transaction); 

      NpgsqlDataReader dr = cmd.ExecuteReader(); 

      if (dr.HasRows) 
      { 
       dr.Read(); 


       idVideo = Convert.ToInt32(dr["idvideo"]); 
       title = dr["title"].ToString(); 

       Validate_Scheduling(idVideo); // 
       result = true; 
      } 

      transaction.Commit(); 
      conn.Close(); 

     } 
     return result; 
    } 
+0

看一看諮詢鎖:http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS –

+1

有點替代做法:如果你讀什麼將未決記錄集設置到主線程中,然後將這些ID傳遞給新的工作線程?每個線程負責從數據庫中獲取細節,完成工作,然後記錄結果。你會消除這種重疊的機會,我猜測性能將是相同的,因爲在線程中完成的工作將是緩慢的部分。 –

回答

1

您有幾種選擇這裏。正如你注意到的,你不想做的一件事是鎖定桌子。

  1. 諮詢鎖。優點是這些是額外的交易。缺點是它們在事務中沒有關閉,並且必須專門關閉,並且泄漏最終會導致問題(實質上是後端共享內存泄漏)。一般來說,我不喜歡像這樣的額外事務性鎖,並且在數據庫會話結束時會清除諮詢鎖,但仍然存在舊狀態鎖的問題。

  2. 您可以讓專用線程首先拉取掛起的文件,然後將特定的檢索委託給子線程。這可能是在數據庫往返和簡單操作方面最好的方法。我希望這可以發揮最好的解決方案。

  3. 您可以在可以處理異常處理的存儲過程中選擇FOR UPDATE NOWAIT。有關示例,請參見Select unlocked row in Postgresql