PostgreSQL中的锁表

时间:2013-02-05 11:57:48

标签: c# .net multithreading 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;
    }

1 个答案:

答案 0 :(得分:1)

这里有几个选项。正如你所注意到的那样,你不想做的一件事是锁定表格。

  1. 咨询锁。优点是这些是额外的交易。缺点是它们在事务处理时并未关闭,必须特别关闭,并且泄漏最终可能导致问题(实质上是后端的共享内存泄漏)。一般来说,我不喜欢像这样的额外事务锁,当db会话结束时清除咨询锁时,仍然存在过时锁的问题。

  2. 您可以先使用专用线程提取待处理文件,然后将特定检索委派给子线程。这可能是数据库往返和操作简单性方面的最佳方法。我希望这可以在任何解决方案中发挥最佳效果。

  3. 您可以在可以处理异常处理的存储过程中SELECT FOR UPDATE NOWAIT。有关示例,请参阅Select unlocked row in Postgresql