Истекло время ожидания простой инструкции Insert в SQL Server

У меня простая таблица с 6 столбцами. В большинстве случаев любые операторы вставки в него работают нормально, но время от времени я получаю исключение тайм-аута БД: Истекло время ожидания. Время ожидания истекло до завершения операции или сервер не отвечает. Заявление было прекращено.

Тайм-аут установлен на 10 секунд.

Я должен упомянуть, что я использую NHibernate и что оператор также включает "select SCOPE_IDENTITY ()" сразу после самой вставки.

Я подумал, что таблица была заблокирована или что-то в этом роде, но в то время не было других операторов, работающих на этой таблице.

Все вставки очень простые, в профилировщике sql все выглядит нормально, в таблице нет индексов, кроме PK (заполненность страницы: 98,57%).

Есть идеи, что мне искать?

Спасибо.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
21
0
35 757
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

посмотрите на фрагментацию таблицы, вы можете получить разбиение страницы из-за этого

no other statements running on that table at that time.

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

Также проверьте, не происходит ли рост файла журнала или файла данных в то время, если вы используете SQL2005, это будет отображаться в журналах ошибок SQL.

на самом деле транзакция вставляется в 3 таблицы, но как она могла заблокировать проблемную таблицу?

Meidan Alon 18.01.2009 12:51

примерно так: 0: начать транзакцию; 1: обновить одну запись в таблице проблем (выполняется быстро); 2: обновить какую-то другую таблицу (занимает много времени); 3: таблица проблем фиксации будет заблокирована до шага 3; если другое задание пытается обновить заблокированную запись, оно будет ждать.

SqlACID 18.01.2009 17:17

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

Самый простой способ узнать об этом - запустить INSERT и, пока он завис, запустить EXEC SP_WHO2 в другом окне на том же сервере. В нем будут перечислены все текущие операции с базой данных и будет столбец BLK, который покажет вам, заблокированы ли какие-либо процессы в данный момент. Проверьте SPID вашего зависшего соединения, чтобы увидеть, есть ли что-нибудь в столбце BLK, и если да, то это процесс, который вас блокирует.

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

Что, если тайм-аут случается время от времени, я не могу «поймать» время, когда это произойдет, чтобы запустить команды отладки?

Serge Shultz 21.05.2015 17:20

как остановить блокирующий процесс?

tichra 10.03.2016 13:57

Я полагаю, если бы ваш тайм-аут составлял 10 секунд, вы могли бы запустить SP_WHO2 (см. Другие ответы) через 8 или 9 секунд и посмотреть, поймал ли он что-то. Это может быть сложно реализовать, но это может быть единственный способ. Конечно, если это удастся, вы бы отменили его, прежде чем он начался.

Simon_Weaver 27.01.2021 10:44

Может быть, стол долго растет.

Если у вас есть таблица, настроенная на большой рост, и у вас не включена мгновенная инициализация файла, то время от времени запрос, безусловно, может отключаться по таймауту.

Проверьте этот беспорядок: MSDN

autogrowth установлен на 1 МБ, может ли выделение 1 МБ занять так много времени?

Meidan Alon 18.01.2009 11:14

@meidan нет, это не займет так много времени, но я бы изменил его, чтобы он увеличивался в гораздо более крупных кусках, или со временем вы получите очень фрагментированную файловую систему, если она будет постоянно расти. по умолчанию - 10%, и это хорошо работает для большинства, кроме очень больших dbs.

SqlACID 18.01.2009 23:17

@Eam - танки! это очень важно при вставке больших объектов

Ali U 05.12.2016 12:53
Ответ принят как подходящий

У нашего QA было несколько подключений к Excel, которые возвращали большие наборы результатов, эти запросы на некоторое время были приостановлены с WaitType ASYNC_NETWORK_IO. В это время истекло время ожидания всех остальных запросов, так что конкретная вставка не имела к этому никакого отношения.

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

В приведенном ниже фрагменте используется соглашение, согласно которому SP_WHO2 возвращает "." текст для BlockedBy для неблокированных запросов, и поэтому он их отфильтровывает и возвращает текст SQL оставшихся запросов (как "жертв", так и "виновников"):

--prepare a table so that we can filter out sp_who2 results
DECLARE @who TABLE(BlockedId INT, 
                   Status VARCHAR(MAX), 
                   LOGIN VARCHAR(MAX), 
                   HostName VARCHAR(MAX), 
                   BlockedById VARCHAR(MAX), 
                   DBName VARCHAR(MAX), 
                   Command VARCHAR(MAX), 
                   CPUTime INT, 
                   DiskIO INT, 
                   LastBatch VARCHAR(MAX), 
                   ProgramName VARCHAR(MAX), 
                   SPID_1 INT, 
                   REQUESTID INT)
INSERT INTO @who EXEC sp_who2

--select the blocked and blocking queries (if any) as SQL text
SELECT 
(
    SELECT TEXT 
    FROM sys.dm_exec_sql_text(
       (SELECT handle 
        FROM (
            SELECT CAST(sql_handle AS VARBINARY(128)) AS handle
            FROM sys.sysprocesses WHERE spid = BlockedId
        ) query)
    )
) AS 'Blocked Query (Victim)',
(
    SELECT TEXT 
    FROM sys.dm_exec_sql_text(
       (SELECT handle 
        FROM (
            SELECT CAST(sql_handle AS VARBINARY(128)) AS handle
            FROM sys.sysprocesses WHERE spid = BlockedById
        ) query)
    )
) AS 'Blocking Query (Culprit)'
FROM @who 
WHERE BlockedById != '  .'

Крысы. В SQL 2000 у меня неправильный синтаксис рядом с 'MAX', EXECUTE нельзя использовать в качестве источника при вставке в переменную таблицы и т. д. Какая версия SQL требуется для этого скрипта? Он работает в SQL 2008, но эта db не моя проблема.

jp2code 26.06.2012 23:13

Вы пробовали использовать временную таблицу вместо табличной переменной?

andreister 29.06.2012 14:20

Извиняюсь за совершенно бесполезный комментарий, но ... Молодец этот человек :) Это сценарий для зала славы. Помог мне решить проблему, которая долгое время преследовала одну из наших систем. +1000

Jimbo 27.03.2018 15:53

Другие вопросы по теме