PostgreSQL中的锁定表
本文关键字:锁定 PostgreSQL | 更新日期: 2023-09-27 17:57:59
我有一个带有一些下载链接的表"Links"。
我的.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;
}
这里有几个选项。正如你所注意到的,你不想做的一件事就是锁桌子。
-
咨询锁。其优点是这些都是额外的事务处理。缺点是它们在事务中没有关闭,必须专门关闭,而且泄漏最终可能会导致问题(本质上是后端的共享内存泄漏)。一般来说,我不喜欢这样的额外事务锁,虽然在数据库会话结束时会清除咨询锁,但陈旧的锁仍然可能存在问题。
-
您可以让一个专用线程先提取挂起的文件,然后将特定的检索委托给子线程。就数据库往返和操作的简单性而言,这可能是最好的方法。我希望这将是所有解决方案中性能最好的。
-
您可以在可以处理异常处理的存储过程中选择FOR UPDATE NOWAIT。有关示例,请参见Postgresql中的Select unlocked行。