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

Вставляет ли данные в SQL Server всю таблицу?

Я использую Entity Framework, и я вставляю записи в нашу базу данных, которые включают поле blob. Поле blob может содержать до 5 Мб данных.

При вставке записи в эту таблицу блокирует ли она всю таблицу?

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

Сколько времени потребуется, прежде чем он закроет тупик? Будет ли это время зависеть от того, сколько нагрузки на сервере, например. если нагрузки не так много, потребуется ли больше времени, чтобы вызвать тупик?

Есть ли способ контролировать и видеть, что заблокировано в какое-то конкретное время?

Если каждый поток выполняет запросы в одиночных таблицах, есть ли случай, когда может произойти блокировка? Не так ли, что тупик может произойти только в том случае, если у вас есть запрос, который имеет соединение и действует на несколько таблиц?

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

4b9b3361

Ответ 1

Святая корова, у вас здесь много вопросов, хе-хе. Вот несколько ответов:

При вставке записи в эту таблицу блокирует ли она всю таблицу?

Не по умолчанию, но если вы используете подсказку TABLOCK или выполняете определенные операции с массовой загрузкой, тогда да.

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

Это становится немного сложнее. Если кто-то пытается выбрать данные со страницы в таблице, которую вы заблокировали, то да, вы заблокируете их. Вы можете обойти это с помощью таких вещей, как подсказка NOLOCK в инструкции select или с помощью функции Read Committed Snapshot Isolation. В качестве отправной точки для того, как работают уровни изоляции, просмотрите Kendra Маленький плакат уровней изоляции.

Сколько времени потребуется, прежде чем он закроет тупик? Будет ли это время зависеть от того, сколько нагрузки на сервере, например. если нагрузки не так много, потребуется больше времени, чтобы вызвать тупик?

Тупики не основаны на времени - они основаны на зависимостях. Скажем, у нас сложилась такая ситуация:

  • Запрос A содержит кучу блокировок, и для завершения его запроса ему нужны вещи, которые блокируются Query B
  • Query B также держит кучу замков, и для завершения его запроса ему нужны вещи, заблокированные Query A

Ни один запрос не может двигаться вперед (думаю, мексиканское противостояние), поэтому SQL Server называет его ничьей, снимает чей-то запрос в спину, выпускает свои блокировки и позволяет другому запросу продолжать работу. SQL Server выбирает жертву, на основе которой будет дешевле отката назад. Если вы хотите получить фантазию, вы можете использовать SET DEADLOCK_PRIORITY LOW в определенных запросах для рисования целей на их спине, и SQL Server начнет их сначала снимать.

Есть ли способ отслеживать и видеть, что заблокировано в какое-то конкретное время?

Абсолютно - там Dynamic Management Views (DMV) вы можете запросить как sys.dm_tran_locks, но самый простой способ - использовать Adam Machanic free sp_WhoIsActive хранимый proc. Это действительно гладкая замена sp_who, которую вы можете вызвать следующим образом:

sp_WhoIsActive @get_locks = 1

Для каждого выполняемого запроса вы получите немного XML, который описывает все блокировки, которые он хранит. Там также столбец "Блокировка", поэтому вы можете видеть, кто блокирует кого. Чтобы интерпретировать удерживаемые блокировки, вам нужно будет проверить "Электронное описание книг" типов блокировок.

Если каждый поток выполняет запросы в одиночных таблицах, есть ли случай, когда может произойти блокировка? Не так ли, что тупик может произойти только в том случае, если у вас есть запрос, который имеет соединение и действует на несколько таблиц?

Верьте или нет, один запрос может фактически зайти в тупик, и да, запросы могут затормозить только на одной таблице. Чтобы узнать больше о тупиках, ознакомьтесь с Сложность с тупиками от Иеремии Пески.

Ответ 2

Если у вас есть прямой контроль над SQL, вы можете принудительно блокировать уровень строк, используя:

INSERT INTO MyTable(Id, BigColumn) WITH (ROWLOCK)
VALUES(...)

Эти два ответа могут быть полезны:

Возможно ли принудительное блокирование уровня строк в SQL Server?

Блокировка таблицы с помощью выбора в Entity Framework

Чтобы просмотреть текущие удерживаемые блокировки в Management Studio, посмотрите под сервером, затем в разделе Управление/Мониторинг активности. В нем есть раздел для блокировок по объекту, поэтому вы должны иметь возможность увидеть, действительно ли вставки создают проблему.

Ответ 3

Лучший ответ, который я могу придумать: это зависит.

Лучший способ проверить - найти SPID соединения и использовать sp_lock SPID, чтобы проверить, является ли режим блокировки X типом TAB. Вы также можете проверить имя таблицы с помощью SELECT OBJECT_NAME(objid). Я также хотел бы использовать следующий запрос для проверки блокировки.

    SELECT RESOURCE_TYPE,RESOURCE_SUBTYPE,DB_NAME(RESOURCE_DATABASE_ID) AS 'DATABASE',resource_database_id DBID,
    RESOURCE_DESCRIPTION,RESOURCE_ASSOCIATED_ENTITY_ID,REQUEST_MODE,REQUEST_SESSION_ID,
    CASE WHEN RESOURCE_TYPE = 'OBJECT' THEN OBJECT_NAME(RESOURCE_ASSOCIATED_ENTITY_ID,RESOURCE_DATABASE_ID) ELSE '' END OBJETO
    FROM SYS.DM_TRAN_LOCKS (NOLOCK)
    WHERE REQUEST_SESSION_ID = --SPID here

В SQL Server 2008 (и более поздних версиях) вы можете отключить эскалацию блокировки в таблице и принудительно использовать WITH (ROWLOCK) в своем предложении insert, эффективно принудительно блокируя строку. Это невозможно сделать до SQL Server 2008 (вы можете писать WITH ROWLOCK, но SQL Server может игнорировать его).

Я говорю генералов здесь, и у меня нет большого опыта работы с BLOB, поскольку я обычно советую разработчикам избегать их, особенно если они больше 1 Мб.

Ответ 4

Ошибки взаимоблокировки обычно возвращаются довольно быстро. Состояния взаимоблокировки не возникают из-за ошибки тайм-аута, возникающей во время ожидания блокировки. Тупик обнаруживается SQL Server, ища циклы в запросах блокировки.