Kueri SQL di Parallel.ForEach - Kebuntuan

Saya memiliki metode statis yang memanggil SQL SP di dalam metode statis dalam loop Parallel.ForEach. SP memasukkan data dalam 3 tabel berbeda. Saya menggunakan level Transaksi Serializable. Namun sesekali saya mengalami situasi Deadlock.

Saya berpikir jika saya menjadikan metode itu sebagai metode Instance atau menggunakan ForEach sederhana, ini mungkin dapat memperbaiki masalah.

Apakah pemikiranku benar? Apakah saya perlu mengunci daftarnya juga?

--Kode--

Parallel.ForEach(MyConcurrentDictionary, MyElement =>
{
   if (MyElement.SomeProperty != SomeValue)
      {
         PublishMessage(MyElement);
      }
      else
      {
         InsertInDatabase(MyElement);

      }
}




public static void InsertInDatabase()
{
   DataTable t1 = new DataTable();
   DataTable t2 = new DataTable();
   DataTable t3 = new DataTable();


   CreateTable(T1);
   CreateTable(T2);
   CreateTable(T3);

   using (var conn = new SqlConnection(ConnString))
      {
         try
            {
               conn.Open();

               // Begin transaction
               using (SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.Serializable))
                  {
                     SqlCommand cmd = new SqlCommand();
                     cmd.Transaction = transaction;
                     cmd.Connection = conn;
                     cmd.CommandType = CommandType.StoredProcedure;
                     cmd.CommandText = "SPName";
                     cmd.Parameters.AddWithValue("@T1", T1);
                     cmd.Parameters.AddWithValue("@T2", T2);
                     cmd.Parameters.AddWithValue("@T3", T3);
                     cmd.ExecuteNonQuery();

                     transaction.Commit();

                }
           }

     }
}

person Asdfg    schedule 01.06.2011    source sumber
comment
Apakah Anda menjalankan semua ini dalam satu transaksi?   -  person Johann Blais    schedule 01.06.2011
comment
@Johann Blais - Setiap elemen membuat Transaksinya sendiri. Transaksi dibuat di dalam Parallel.ForEach.   -  person Asdfg    schedule 01.06.2011
comment
Ini mungkin tidak layak untuk multithreading. Jika Anda melakukan penyisipan SQL, Anda mungkin akan lebih terikat pada IO daripada terikat pada CPU.   -  person fire.eagle    schedule 01.06.2011
comment
Apakah Anda benar-benar memerlukan isolasi Serializable; pertimbangkan untuk turun ke Read Commited (default SQL Server).   -  person Polyfun    schedule 01.06.2011
comment
@ShellShock - Saya telah Read Commited sebelumnya tetapi sedang mengalami situasi Deadlock jadi saya mengubahnya menjadi Serializable.   -  person Asdfg    schedule 01.06.2011
comment
Apakah Anda memiliki kode yang dapat Anda posting?   -  person Brian Gideon    schedule 01.06.2011
comment
Adakah potensi SP menimbulkan kebuntuan?   -  person SWeko    schedule 01.06.2011
comment
@Brian Gideon - Mengedit pertanyaan dengan kode   -  person Asdfg    schedule 01.06.2011
comment
Juga kode di SP akan sangat membantu. Kemungkinan besar di sanalah Anda akan menemukan alasan kebuntuan tersebut.   -  person Mikael Eriksson    schedule 01.06.2011
comment
IsolationLevel.Serializable ITU JAHAT!!! Ini adalah pengaturan paling intensif kunci yang bisa Anda dapatkan. Apakah kamu yakin menginginkan ini? Saya ragu Anda melakukannya... Serializable di Sql Server akan meningkatkan kunci dengan sangat cepat ke rentang dan kunci tabel. Jika Anda memiliki throughput apa pun, kebuntuan pasti akan terjadi. ReadCommitted adalah yang Anda cari, dan ini adalah level isolasi default di server Sql, Serializable adalah level default di .Net.   -  person Didaxis    schedule 07.10.2013


Jawaban (2)


Cobalah untuk mengubah kelas Anda ke metode non statis yang akan banyak membantu. JANGAN PERNAH menggunakan statika secara paralel, ini hanya akan menimbulkan masalah. Dan untuk keamanan coba gunakan daftar simpanan thread alias daftar array yang disinkronkan atau System.Collections.Concurrent.ConcurrentQueue(Of T).

Salam

person orophine    schedule 04.06.2012

Anda mendapatkan masalah karena Anda tidak menggunakan sinkronisasi apa pun. Kata kunci static tidak berarti aman untuk thread. Beberapa thread dari Parallel.ForEach masih dapat mengakses metode ini secara bersamaan.

Anda memiliki banyak opsi untuk menyinkronkannya. Tapi saya akan mulai dengan yang paling mudah, menjadikannya single threaded. Jika tidak memungkinkan, gunakan lock atau lihat opsi lain

PERBARUI
Seperti yang diperhatikan oleh @Colin, jawaban saya berfungsi jika Anda memperbarui data di suatu tempat. Jika semuanya hanya-baca, maka ada hal lain. Periksa pembuatan DataTable.

person oleksii    schedule 01.06.2011
comment
Belum tentu. Tidak ada yang ditampilkan yang akan menyebabkan masalah sinkronisasi thread dalam kode C#. (Namun, ada kode yang hilang yang mungkin menimbulkan masalah). Tidak apa-apa untuk memanggil metode statis secara bersamaan jika metode tersebut tidak berbagi data dengan thread lain (atau data apa pun yang dibagikan murni hanya dapat dibaca di semua thread) - person Colin Mackay; 01.06.2011
comment
@Colin Saya berasumsi bahwa pembuatan DataTable kemungkinan besar merupakan thread yang tidak aman. - person oleksii; 02.06.2011
comment
Setiap metode bersifat statis. Saya benci jika orang melakukan hal itu padahal lebih masuk akal untuk menjadikan metode sebagai metode contoh. Ini bukanlah metode utilitas. Metode ini melakukan operasi database. - person Asdfg; 02.06.2011
comment
@Asdfg, bisakah Anda memfaktorkannya kembali menjadi metode instan atau terlalu merepotkan? - person oleksii; 02.06.2011
comment
Itulah yang akan saya lakukan selanjutnya. - person Asdfg; 02.06.2011