แบบสอบถาม SQL ใน Parallel.ForEach - Deadlock

ฉันมีวิธีการคงที่ซึ่งเรียก SQL SP ภายในวิธีการคงที่ใน Parallel.ForEach loop SP แทรกข้อมูลใน 3 ตารางที่แตกต่างกัน ฉันกำลังใช้ระดับธุรกรรมแบบอนุกรม แต่บางครั้งฉันก็ประสบปัญหาการหยุดชะงัก

ฉันคิดว่าถ้าฉันสร้างวิธีนั้นเป็นวิธีอินสแตนซ์หรือใช้ ForEach แบบธรรมดาก็อาจแก้ไขปัญหาได้

ฉันคิดถูกหรือเปล่า? ฉันจำเป็นต้องล็อครายการด้วยหรือไม่?

--รหัส--

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 แหล่งที่มา
comment
คุณดำเนินการทั้งหมดนี้ในธุรกรรมเดียวหรือไม่?   -  person Johann Blais    schedule 01.06.2011
comment
@Johann Blais - แต่ละองค์ประกอบสร้างธุรกรรมของตัวเอง ธุรกรรมถูกสร้างขึ้นภายใน Parallel.ForEach   -  person Asdfg    schedule 01.06.2011
comment
นี่อาจไม่คุ้มค่ากับการทำงานแบบมัลติเธรด หากคุณกำลังทำการแทรก SQL คุณอาจจะผูกกับ IO มากกว่าผูกกับ CPU   -  person fire.eagle    schedule 01.06.2011
comment
คุณต้องการการแยกแบบอนุกรมหรือไม่ พิจารณาดรอปดาวน์เพื่ออ่านความมุ่งมั่น (ค่าเริ่มต้นของ SQL Server)   -  person Polyfun    schedule 01.06.2011
comment
@ShellShock - ฉันได้ Read Commited ก่อนหน้านี้ แต่มันกำลังเข้าสู่สถานการณ์ Deadlock ดังนั้นฉันจึงเปลี่ยนเป็น Serializable   -  person Asdfg    schedule 01.06.2011
comment
คุณมีรหัสใด ๆ ที่คุณสามารถโพสต์ได้หรือไม่?   -  person Brian Gideon    schedule 01.06.2011
comment
SP มีศักยภาพที่จะทำให้เกิดการหยุดชะงักหรือไม่?   -  person SWeko    schedule 01.06.2011
comment
@Brian Gideon - แก้ไขคำถามด้วยรหัส   -  person Asdfg    schedule 01.06.2011
comment
รหัสใน SP ก็มีประโยชน์เช่นกัน เป็นไปได้มากว่าคุณจะพบสาเหตุของการหยุดชะงัก   -  person Mikael Eriksson    schedule 01.06.2011
comment
IsolationLevel.Serializable ชั่วร้าย!!! เป็นการตั้งค่าที่เน้นการล็อคมากที่สุดที่คุณจะได้รับ คุณแน่ใจหรือว่าต้องการสิ่งนี้? ฉันสงสัยว่าคุณทำ ... Serializable ใน Sql Server จะเพิ่มการล็อคอย่างรวดเร็วไปยังช่วงและการล็อคตาราง หากคุณมีปริมาณงานใดๆ การหยุดชะงักจะต้องตามมาอย่างแน่นอน ReadCommitted คือสิ่งที่คุณกำลังมองหา และเป็นระดับการแยกเริ่มต้นในเซิร์ฟเวอร์ Sql Serializable คือระดับเริ่มต้นใน .Net   -  person Didaxis    schedule 07.10.2013


คำตอบ (2)


ลองเปลี่ยนคลาสของคุณเป็นวิธีแบบไม่คงที่ซึ่งจะช่วยได้มาก อย่าใช้สถิตศาสตร์ควบคู่กัน มันเป็นเพียงการถามถึงปัญหา และเพื่อความปลอดภัย ลองใช้รายการบันทึกเธรดหรือที่เรียกว่ารายการอาร์เรย์ที่ซิงโครไนซ์หรือ System.Collections.Concurrent.ConcurrentQueue(Of T)

ขอแสดงความนับถือ

person orophine    schedule 04.06.2012

คุณได้รับปัญหาเนื่องจากคุณไม่ได้ใช้การซิงโครไนซ์ใดๆ คีย์เวิร์ด static ไม่ได้หมายความว่าเป็นเธรดที่ปลอดภัย หลายเธรดจาก Parallel.ForEach ยังคงสามารถเข้าถึงวิธีนี้ได้ในเวลาเดียวกัน

คุณมีตัวเลือกมากมายในการซิงค์สิ่งนั้น แต่ฉันจะเริ่มต้นด้วยวิธีที่ง่ายที่สุด ทำให้เป็นเธรดเดี่ยว หากเป็นไปไม่ได้ ให้ใช้ lock หรือดูตัวเลือกอื่นๆ

อัปเดต
ตามที่ @Colin สังเกตเห็น คำตอบของฉันใช้ได้หากคุณอัปเดตข้อมูลที่ไหนสักแห่ง หากทุกอย่างเป็นแบบอ่านอย่างเดียวก็ยังมีอย่างอื่นอยู่ ตรวจสอบการสร้าง DataTable

person oleksii    schedule 01.06.2011
comment
ไม่จำเป็น. ไม่มีสิ่งใดที่แสดงว่าอาจทำให้เกิดปัญหาการซิงโครไนซ์เธรดในโค้ด C# (แต่มีรหัสหายไปซึ่งอาจมีปัญหา) เป็นการดีอย่างยิ่งที่จะเรียกใช้เมธอดแบบคงที่พร้อมกัน หากไม่ได้แชร์ข้อมูลกับเธรดอื่น (หรือข้อมูลใด ๆ ที่แชร์จะถูกอ่านอย่างเดียวในทุกเธรดเท่านั้น) - person Colin Mackay; 01.06.2011
comment
@Colin ฉันคิดว่าการสร้าง DataTable มีแนวโน้มที่จะเป็นเธรดที่ไม่ปลอดภัย - person oleksii; 02.06.2011
comment
ทุกวิธีเป็นแบบคงที่ ฉันเกลียดเวลาที่ผู้คนทำอย่างนั้นเมื่อมันสมเหตุสมผลกว่าที่จะสร้างวิธีการเช่นวิธีการ สิ่งเหล่านี้ไม่ใช่วิธีการอรรถประโยชน์ วิธีการเหล่านี้ดำเนินการฐานข้อมูล - person Asdfg; 02.06.2011
comment
@Asdfg คุณสามารถปรับโครงสร้างใหม่ให้เป็นวิธีการอินสแตนซ์หรือใช้งานได้มากเกินไปหรือไม่? - person oleksii; 02.06.2011
comment
นั่นคือสิ่งที่ฉันกำลังจะทำต่อไป - person Asdfg; 02.06.2011