Подтвердить что ты не робот

Поиск и устранение неисправностей в SQL Server 2008

Мой веб-сайт, похоже, не обрабатывает большое количество посетителей, я считаю, потому что сервер слишком прост.

2 часа назад на моем сайте было много хитов, и я заметил, что произошло 3 ошибки взаимоблокировки, ошибка:

System.Data.SqlClient.SqlException: Транзакция (идентификатор процесса 58) была заблокирована при блокировке ресурсов другим процессом и была выбрана в качестве жертвы взаимоблокировки. Перезапустите транзакцию.

Я не уверен, почему это произошло... Посмотрев на трассировку стека, я понял, что это произошло с запросом select.

Кто-нибудь знает, что может быть причиной этой ошибки?

Сервер работает под управлением Windows 2008 и Sql Server 2008.

4b9b3361

Ответ 1

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

Ответ 2

SQL Server 2008 имеет несколько способов идентификации процессов и запросов, связанных с тупиком.

  • Если взаимоблокировки легко воспроизводить, частота выше, и вы можете профилировать SQL-сервер (у вас есть доступ и производительность на сервере, когда профилировщик включен) с использованием SQL Profiler даст вам хороший графический вид тупика. На этой странице есть вся информация, необходимая для использования кривых взаимоблокировки http://sqlmag.com/database-performance-tuning/gathering-deadlock-information-deadlock-graph

  • Большая часть времени, воспроизводящая взаимоблокировки, является сложной, или они происходят в производственной среде, где мы не хотим прикреплять к ней Profiler и влиять на производительность.

Я бы использовал этот запрос, чтобы получить взаимоблокировки:

SELECT
  xed.value('@timestamp', 'datetime') as Creation_Date,
  xed.query('.') AS Extend_Event
FROM
(
  SELECT CAST([target_data] AS XML) AS Target_Data
  FROM sys.dm_xe_session_targets AS xt
  INNER JOIN sys.dm_xe_sessions AS xs
  ON xs.address = xt.event_session_address
  WHERE xs.name = N'system_health'
  AND xt.target_name = N'ring_buffer'
) AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xed)
ORDER BY Creation_Date DESC

Я бы не пошел в направлении использования (NOLOCK), чтобы исправить взаимоблокировки. Это скользкий склон и скрытие исходной проблемы.

Ответ 3

Если вы не против грязных чтений, вы можете попробовать положить (NOLOCK) после имен таблиц в свои запросы SELECT. Компромисс здесь заключается в том, что вам не гарантируются самые современные данные, поскольку инструкции UPDATE и INSERT, выполняемые в настоящее время, игнорируются.

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

Альтернативно посмотрите http://www.sql-server-performance.com/tips/deadlocks_p1.aspx