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;
    }

PostgreSQL中的锁定表

这里有几个选项。正如你所注意到的,你不想做的一件事就是锁桌子。

  1. 咨询锁。其优点是这些都是额外的事务处理。缺点是它们在事务中没有关闭,必须专门关闭,而且泄漏最终可能会导致问题(本质上是后端的共享内存泄漏)。一般来说,我不喜欢这样的额外事务锁,虽然在数据库会话结束时会清除咨询锁,但陈旧的锁仍然可能存在问题。

  2. 您可以让一个专用线程先提取挂起的文件,然后将特定的检索委托给子线程。就数据库往返和操作的简单性而言,这可能是最好的方法。我希望这将是所有解决方案中性能最好的。

  3. 您可以在可以处理异常处理的存储过程中选择FOR UPDATE NOWAIT。有关示例,请参见Postgresql中的Select unlocked行。