2009-06-13 2 views
9

Я пишу некоторый код регистрации/аудита, который будет работать в процессе производства (не только при возникновении ошибок или при разработке). Прочитав Coding Horror's experiences with dead-locking and logging, я решил обратиться за советом. (Решение Джеффа «не регистрировать» для меня не сработает, это юридически подтвержденный аудит безопасности)Рекомендации по минимизации блокировки при добавлении только таблицы в MS SQL Server?

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

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

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

+0

какая версия сервера sql? –

+0

SQL 2000, хотя слухи о том, что когда-нибудь офис перейдет на SQL 2008. – MatthewMartin

ответ

5

Обычная транзакция (то есть READ COMMITTED) вставки уже выполняет «минимальную» блокировку. Вставка интенсивных приложений не будет блокироваться на вставке, независимо от порядка смешивания вставки с другими операциями. В худшем случае интенсивная система вставки может вызвать конфликт заслонки страницы в горячей точке, где происходит вставка, но не взаимоблокировки.

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

  • Система использует более высокий уровень изоляции (они его ближайшие тогда и хорошо заслужили)
  • Они читали из таблицы журнала во время операции (так больше не «добавлять только»)
  • тупик цепь участвует слой блокировки приложений (например. .Net lock заявления в рамках log4net), в результате незаметного тупики (т. е. зависание приложения). Учитывая, что решение проблемы связано с процессами, я предполагаю, что это сценарий, который они имели.

До тех пор, пока вы вставляете только вход в транзакции уровня изоляции READ COMMITTED, вы в безопасности. Если вы ожидаете ту же проблему, я подозреваю, что SO (т. Е. Взаимоблокировки, связанные с блокировками на уровне приложений), то никакое количество мастеров базы данных не сможет вас спасти, так как проблема может проявляться даже при входе в отдельную транзакцию или в отдельное соединение.

+1

«До тех пор, пока вы вставляете только вход в транзакции уровня изоляции READ COMMITTED, вы в безопасности». Это неправда. Если вы участвуете в большой транзакции, вы можете заблокировать всю транзакцию при попытке вставить материал в таблицу протоколирования (если таблица протоколирования заблокирована, потому что вы запускаете какой-то сумасшедший отчет или что-то подобное). Кроме того, это открывает вам центральную точку взаимоблокировки! –

+2

Нет, просто неправда. INSERT будет * не * блокировать отчет (прочитанный), независимо от того, что вы делаете в транзакции. Также одновременные INSERTS никогда не появятся в цепочке взаимоблокировок, опять же потому, что они не блокируются друг за другом, а не за SELECT. То, что может заблокировать вставку, - это блокировка диапазона S, которая покрывает точку вставки (то есть сериализуемый отчет), блокировку S на таблице (то есть эскалацию из повторяемого отчета) или блокировку X (то есть некоторую активность * другую *, чем «добавить только», например, обновления, которые перешли на блокировку таблицы X). –

+2

INSERT в таблицу (с кластеризованным индексом) в прочитанном объявлении получает блокировку IX на странице и X блокировку ключа. Если он не может получить блокировку IX на странице, она будет ждать, если она не сможет получить, а блокировка X на ключе будет ждать. Операторы SELECT должны иметь общие блокировки. Блокировки могут конфликтовать. Тупики могут существовать. Читайте: http://msdn.microsoft.com/en-us/library/ms186396.aspx –

1

Поскольку вы не заботитесь о целостности транзакции таблицы аудита, вы, очевидно, можете выполнять регистрацию вне транзакции (т. Е. После ее завершения). Это минимизирует влияние на транзакцию.

Кроме того, если вы хотите свести к минимуму блокировку, вам следует попытаться обеспечить максимально возможную нагрузку на ваш запрос на некластеризованные индексы. (SQL Server 2005 и выше, использование оператора INCLUDE в индексах NC может иметь большое значение)

+0

Примечание: если вы выполните все протоколирование после завершения транзакции, довольно сложно отлаживать длительные транзакции или прерванные транзакции. –

+0

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

+0

все, что говорится в этом контексте (то есть в отдельном потоке), вероятно, лучше (т.е. после его завершения) –

1

Один простой способ предотвратить блокировку журналов от вашей «обычной» базы данных - не использовать одну и ту же базу данных , Просто создайте другую базу данных для ведения журнала. В качестве бонуса быстрый рост базы данных ведения журнала не приведет к фрагментации в вашей основной БД. Personall, я обычно предпочитаю записывать в файл, но опять же, я привык делать тяжелые манипуляции с текстом в своем редакторе - VIM. Вход в отдельную БД должен помочь избежать проблем с блокировкой.

Просто убедитесь, что если вы попробуете написать свой собственный аддон базы данных для используемой вами структуры ведения журнала, вы будете очень осторожны в своих блокировках (что я догадываюсь, это то, что сработало Jeff в блоге, которое вы ссылаетесь). Правильно написано (см. Несколько комментариев в сообщении Джеффа), у вас не должно быть проблем с блокировкой в ​​вашей системе ведения журнала, если они ничего не делают нечетное.

+0

Я думаю, что введение всей новой базы данных только для таблицы протоколирования довольно агрессивное, вы всегда можете контролировать место хранения каждой таблицы с использованием файловых групп, если это необходимо. Также не то, что если вы распределили транзакцию, то регистрация в отдельном db может существенно ухудшить работу, если эта операция участвует в распределенной транзакции. –

+0

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

5

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

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

Захват трассировки стека и всех ваших данных ведения журнала в потоке ведения журнала, chuck it on a queue при появлении новых сообщений о регистрации, сбросьте их в базу данных за одну транзакцию.

шаги к минимизирующему замку:

  • (KEY) выполняют все добавляют к таблице регистрации за пределами основного потока/соединения/транзакции.
  • Убедитесь, что таблица регистрации имеет монотонно увеличивающийся кластерный индекс (например, идентификатор int), который увеличивается при каждом добавлении сообщения журнала. Это гарантирует, что вставляемые страницы обычно находятся в памяти и избегают ударов производительности, получаемых с помощью кучных таблиц.
  • Выполнение нескольких добавлений к протоколу транзакции (10 вложений в транзакции быстрее, чем 10 вставок из транзакции и, как правило, получение/освобождение меньше блокировок)
  • Дайте ему передышку. Выполняйте только регистрацию на свой db каждые N миллисекунд. Запуск бит работ.
  • Если вам нужно сообщать о событиях исторически, вы можете рассмотреть возможность разбивки вашей таблицы ведения журналов. Пример. Каждый месяц вы можете создавать новую таблицу протоколирования и в то же время иметь доступ к журналу VIEW, который является UNION ALL всех старых таблиц ведения журналов. Выполните отчетность против наиболее подходящего источника.

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