1

いくつかのダウンロードリンクを含むテーブル「リンク」があります。

私の.NETアプリケーションはこのテーブルを読み取り、リンクを取得し、Webクライアントを作成して、関連するファイルをダウンロードします。これを行う複数のスレッドを作成したいのですが、それぞれが異なるレコードを読み取る必要があります。そうしないと、2つのスレッドが同じファイルをダウンロードしようとします。どうすればこれを行うことができますか?

私はこれを試しましたが、機能しません:

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

1 に答える 1

1

ここにはいくつかのオプションがあります。お気づきのように、やりたくないことの 1 つは、テーブルをロックすることです。

  1. アドバイザリ ロック。利点は、これらがトランザクション外であることです。欠点は、それらがトランザクションで閉じられず、明示的に閉じる必要があり、そのリークが最終的に問題を引き起こす可能性があることです (基本的にはバックエンドでの共有メモリ リーク)。一般的に言えば、私はこのようなトランザクション外のロックは好きではなく、db セッションが終了するとアドバイザリ ロックはクリアされますが、古いロックにはまだ問題がある可能性があります。

  2. 最初に保留中のファイルをプルする専用スレッドを作成してから、特定の取得を子スレッドに委譲することができます。これは、db のラウンドトリップと操作の単純さの両方の点で、おそらく最良のアプローチです。これがどのソリューションよりも優れたパフォーマンスを発揮することを期待しています。

  3. 例外処理を処理できるストアド プロシージャで SELECT FOR UPDATE NOWAIT を実行できます。例については、Postgresql でロックされていない行を選択するを参照してください。

于 2013-02-17T01:44:41.513 に答える