CREATE TRIGGER занимает более 30 минут на SQL Server 2005

В нашей реальной/производственной базе данных я пытаюсь добавить триггер в таблицу, но безуспешно. Я пытался несколько раз, но для завершения оператора триггера создания потребовалось более 30 минут, и я отменил его.

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

Я не думаю, что есть проблема с самим оператором создания триггера. Оператор создания триггера был успешным и быстрым в тестовой среде, и триггер работает правильно, когда строки вставляются/обновляются в таблицу. Хотя, когда я создал триггер в тестовой базе данных, нагрузка на таблицу была невелика, и в ней было значительно меньше строк, чем в реальной/производственной базе данных (100 против 13 000 000+).

Вот оператор создания триггера, который я пытаюсь запустить

CREATE TRIGGER [OnItem_Updated] 
    ON  [Item]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    IF update(State)
    BEGIN
        /* do some stuff including for each row updated call a stored 
          procedure that increments a value in table based on the 
          UserId of the updated row */
    END
END

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

В SQLServer триггеры создаются включенными по умолчанию. Можно ли сделать триггер отключенным по умолчанию?

Любые другие идеи?


person Adam Porad    schedule 23.10.2008    source источник


Ответы (5)


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

Используйте sp_who, чтобы узнать, откуда исходит блок, а затем исследуйте его оттуда.

person Tom H    schedule 23.10.2008
comment
Запуск функции sp_who во время выполнения оператора триггера create помог мне решить проблему. Был старый сеанс с другого сервера, который был приостановлен, поскольку на нем была блокировка стабильности схемы для таблицы, поэтому я не смог создать триггер. - person Adam Porad; 24.10.2008

Я полагаю, что CREATE Trigger попытается заблокировать всю таблицу.

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

Для любых изменений схемы вы действительно должны получить всех в базе данных.

Тем не менее, заманчиво внести «небольшие» изменения с активными соединениями. Вы должны взглянуть на блокировки / соединения, чтобы увидеть, где конфликт блокировок.

person DJ.    schedule 23.10.2008

Это странно. Триггеру AFTER UPDATE не нужно проверять существующие строки в таблице. Я предполагаю, что вы не можете получить блокировку таблицы, чтобы добавить триггер.

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

person Dave DuPlantis    schedule 23.10.2008

Частью проблемы может быть и сам триггер. Мог ли ваш триггер случайно обновить все строки таблицы? Существует большая разница между 100 строками в тестовой базе данных и 13 000 000 строк. Очень плохая идея разрабатывать код для такого небольшого набора данных, когда у вас такой большой набор данных, что вы не можете предсказать производительность. SQL, который отлично работает для 100 записей, может полностью заблокировать систему с миллионами на несколько часов. Вы действительно хотите знать это в разработке, а не когда продвигаетесь в производство.

Вызов хранимой процедуры в триггере обычно является очень плохим выбором. Это также означает, что вам нужно перебирать записи, что является еще худшим выбором в триггере. Триггеры должны в обязательном порядке учитывать множественные вставки/обновления или удаления записей. Если кто-то вставит 100 000 строк (что маловероятно, если у вас есть 13 000 000 записей), то зацикливание хранимой процедуры на основе записей может занять несколько часов, заблокировать всю таблицу и заставить всех пользователей выследить разработчика и убить (или, по крайней мере, покалечить) его, потому что они не могут выполнить свою работу.

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

Мой друг Деннис написал эту статью, которая иллюстрирует, почему тестирование небольшого объема информации, когда у вас есть большой объем информации, может создать трудности на prd, которые вы не заметили на dev: http://blogs.lessthandot.com/index.php/DataMgmt/?blog=3&title=ваш-испытательныйстенд-имеет-тотже-том&disp=single&more=1&c=1&tb=1&pb=1#c1210

person HLGEM    schedule 02.06.2009

Запустите DISABLE TRIGGER triggername ON tablename перед изменением триггера, затем снова включите его с помощью ENABLE TRIGGER triggername ON tablename

person Marco Marsala    schedule 01.06.2016