ADO.NET DeadLock - PullRequest
       22

ADO.NET DeadLock

0 голосов
/ 03 ноября 2010

У меня периодически возникает тупиковая ситуация со следующим (упрощенным) кодом.

DataSet my_dataset = new DataSet()
SqlCommand sql_command = new SqlCommand();

sql_command.Connection = <valid connection>
sql_command.CommandType = CommandType.Text;
sql_command.CommandText = 'SELECT * FROM MyView ORDER BY 1'

SqlDataAdapter data_adapter = new SqlDataAdapter(sql_command);

sql_command.Connection.Open();

data_adapter.Fill(my_dataset);

sql_command.Connection.Close();

Я получаю ошибку:

Транзакция (идентификатор процесса 269) была заблокирован на ресурсах блокировки с другой процесс и был выбран в качестве жертва тупика. Перезапустите сделка.

Насколько я понимаю, простое заполнение DataSet с помощью команды ADO.Net .Fill () не должно создавать блокировку базы данных. И, как видно из сообщения об ошибке, блокировка принадлежит другому процессу. В представлении, к которому я обращаюсь, есть только операторы select, но оно объединяет несколько таблиц.

  • Могут ли заблокированные записи повлиять на представление, в котором выполняется только оператор выбора?
  • Может / ADO.Net .Fill () блокировать записи?
  • Предполагая, что мне нужно заполнить DataSet, есть ли способ сделать так, чтобы избежать потенциальных блокировок данных?

SQL Server 2005 (9.0.4035)

Ответы [ 3 ]

2 голосов
/ 03 ноября 2010

Запрос на выборку с объединениями действительно может вызвать тупик.Одним из способов решения этой проблемы является выполнение запроса в SqlTransaction с использованием изоляции моментальных снимков.

using(SqlTransaction sqlTran = connection.BeginTransaction(IsolationLevel.Snapshot))
{
    // Query goes here.
}

Может произойти взаимоблокировка, поскольку она блокирует каждую таблицу, соединяемую одну за другой, перед выполнением объединения.Если другой запрос имеет блокировку для таблицы, которую необходимо заблокировать для другого запроса, и наоборот, существует мертвая блокировка.С Snapshot Isolation запросы, которые только что читают из таблиц, не блокируют их.Целостность поддерживается, потому что чтение фактически выполняется из моментального снимка данных в момент начала транзакции.

Это может оказать негативное влияние на производительность, хотя из-за накладных расходов на необходимость создания моментальных снимков.В зависимости от приложения, может быть лучше не использовать изоляцию моментальных снимков, а вместо этого, если запрос не удается, перейдите в тупик, подождите немного и попробуйте снова.

Также может быть лучше попытаться выяснить это.почему возникают взаимоблокировки и изменить структуру базы данных и / или изменить приложение, чтобы предотвратить взаимоблокировки.Эта статья содержит больше информации.

1 голос
/ 03 ноября 2010

Вы можете попробовать это:

  • Понизьте уровень транзакции для этого запроса (например, IsolationLevel.ReadUncommited).
  • Используйте подсказку NOLOCK для вашего запроса.
0 голосов
/ 03 ноября 2010

Это может быть далеко, а не решение вашей проблемы, сначала проверьте другие решения - но у нас была похожая проблема (выборка, которая блокирует записи!), Которую после больших усилий мы отслеживали на уровне файлов / SMB.Казалось, что при большой нагрузке чтение файлов с сетевого диска (SAN) задерживается, создавая ожидающую блокировку чтения для реальных файлов базы данных.Это выражается в блокировке содержащихся записей.

Но это было состояние гонки и не воспроизводилось без нагрузки на диски.Да, это был и SQL Server 2005.

Вы должны быть в состоянии определить с помощью инструментов, входящих в состав SQL Server, какие транзакции взаимоблокируют друг друга.

...