我有一个表“链接”与一些下载链接。
我的.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 :(得分:1)
这里有几个选项。正如你所注意到的那样,你不想做的一件事是锁定表格。
咨询锁。优点是这些是额外的交易。缺点是它们在事务处理时并未关闭,必须特别关闭,并且泄漏最终可能导致问题(实质上是后端的共享内存泄漏)。一般来说,我不喜欢像这样的额外事务锁,当db会话结束时清除咨询锁时,仍然存在过时锁的问题。
您可以先使用专用线程提取待处理文件,然后将特定检索委派给子线程。这可能是数据库往返和操作简单性方面的最佳方法。我希望这可以在任何解决方案中发挥最佳效果。
您可以在可以处理异常处理的存储过程中SELECT FOR UPDATE NOWAIT。有关示例,请参阅Select unlocked row in Postgresql。