2017-01-02 2 views
-1

У меня есть программа C#, работающая с базой данных SQL Server, работающей на разных клиентских компьютерах. Теперь я получаю это исключение, которое [если не поймают] закрывает мое заявление:Исключение исключений в блокировке блокировки связи в C#/SQLSERVER

Transaction (идентификатор процесса ...) был заведен в тупик на замок | связь буферных ресурсов с другим процессом и был выбран как жертва тупика . Перезапустите транзакцию.

и трассировки стека показывает, что исключение происходит здесь:

в Gui.DB.sqlServerWrapper.MarkAsNonFreshSample (String штрих-код, Int32 Девид)

Где упомянутый метод заключается в следующем :

 public void MarkAsNonFreshSample(string barcode, int devID) 
     { 
      mux.WaitOne(); 
      var sql = "DELETE FROM results WHERE [email protected] AND [email protected]"; 
      var command = new SqlCommand(sql, conn); 
      command.Parameters.AddWithValue("barcode", barcode); 
      command.Parameters.AddWithValue("devID", devID); 
      command.ExecuteNonQuery(); 
      mux.ReleaseMutex(); 
     } 

Я использую мьютексы mux для эксклюзивного доступа к соединению sql " conn ", потому что моя программа имеет несколько потоков.

Я не использую сложный запрос или длинную транзакцию (и я предполагаю, что этот короткий запрос является одной транзакцией, которая не должна вызывать тупик. Я ошибаюсь?).

Где проблема и как ее исправить?

+2

* Удалить * мьютекс и глобальной связи. Глобальные соединения гарантируют взаимоблокировки и просто невозможно восстановить в случае ошибки. Соединения должны оставаться открытыми как можно меньше времени –

+0

Можете ли вы восстановить [тупиковый график] (http://dba.stackexchange.com/questions/10644/deadlock-error-isnt-returning-the-deadlock-sql/10646# 10646) и включить его в свой вопрос? –

ответ

2

Совместное соединение, как это не является хорошей практикой

public void MarkAsNonFreshSample(string barcode, int devID) 
{ 
    using (SqlConnection con = new SqlConnection(conString)) 
    { 
     con.Open(); 
     using (SqlCommand command = con.CreateCommand()) 
     { 
      command.CommandText = "DELETE FROM results WHERE [email protected] AND [email protected]"; 
      command.Parameters.AddWithValue("barcode", barcode); 
      command.Parameters.AddWithValue("devID", devID); 
      command.ExecuteNonQuery(); 
     } 
    } 
} 
+0

вы определенно правы. Но (1) это проблема? (2) Я использую этот подход, потому что, если мои потоки взаимодействуют с базой данных несколько сотен раз в секунду, и если я открою и закрою соединение, это, вероятно, будет стоить мне больше – Akhir

+0

Повторяю. Совместное использование такого соединения ** не является хорошей практикой. – Paparazzi

+1

@Akhir, используя глобальное соединение с длинным ходом * и * мьютекс будет создавать большие проблемы независимо от того, что. Достаточно длинного соединения достаточно, чтобы накапливать блокировки и вызывать взаимоблокировки. Все, что вы читаете с этим соединением, приобретает блокировку Select, а это означает, что в первый раз, когда кто-то пытается выполнить обновление, вы получите тупик. –