Выберите из таблицы, которая постоянно вставляется в

#sql #sql-server-2008 #select #insert #deadlock

#sql #sql-сервер-2008 #выберите #вставить #взаимоблокировка

Вопрос:

Как бы я мог собирать данные из таблицы, которая ПОСТОЯННО вставляется (и должна быть), не вызывая какой-либо блокировки, чтобы вставки оставались незамеченными.

Я огляделся и нашел select с опцией nolock, но, если я правильно понимаю, это не останавливает создание блокировки, а обходит текущие блокировки и захватывает все?

Спасибо.

РЕДАКТИРОВАТЬ: эта таблица никогда не будет ОБНОВЛЯТЬСЯ, только ВСТАВЛЯТЬ и ВЫБИРАТЬ

Комментарии:

1. Хотя использование NOLOCK or NO COMMIT level будет работать для этого (хотя вы, вероятно, получите грязные чтения), вы должны иметь возможность безопасно использовать READ COMMITTED (или эквивалент). Поскольку вы не обновляете, у вас не должно возникнуть проблем с конфликтом блокировок (он пропустит все, что было вставлено, но еще не зафиксировано).

2. Да, и грязное чтение — это определенно то, чего я не хочу, поскольку этот процесс будет довольно важным. Я обнаружил, что я буду делать около 250 вставок в минуту из нескольких источников, и я хочу убедиться, что эти вставки продолжаются, не блокируясь моим выбором. Я не планирую индексировать, поскольку индекс будет быстро фрагментирован (или я так считаю)

3. Я не в курсе, как они реализованы (и я никогда не использовал SQL Server), но я думаю, что ваш Clustered Index (особенно над чем-то вроде rowId or insertTimestamp ) может индексироваться не фрагментарным способом (кто-нибудь еще может это взвесить?).

4. Мне действительно нужно разобраться в своих фактах, но парень, который знал, был на обеде, его около 500-600 вставок в минуту :-/

Ответ №1:

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

Документы Microsoft по изоляции транзакций: http://msdn.microsoft.com/en-us/library/ms173763.aspx

NOLOCK — это распространенный и, на мой взгляд, злоупотребляемый вариант, когда сталкиваешься с подобными ситуациями. Хотя это может помочь вам преодолеть проблемы в ситуациях высокой конкуренции, это также может затруднить отслеживание ошибок. Хотя это что-то вроде непрекращающегося спора, проверьте http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx чтобы получить представление о некоторых рисках, связанных с использованием подобных подсказок.

Комментарии:

1. Хм … таким образом, использование nolock может вызвать огромные проблемы из-за полного отсутствия данных. Это важная часть, в которой не может произойти что-то подобное. Нет ли способа выбрать нужные мне данные, пока вставки продолжают функционировать без помех?

2. @Antares — Вы упоминаете в другом месте, что ожидаете вставки в таблицу каждую секунду или около того. Если это действительно так (60 вставок в минуту или около того), у вас не должно возникнуть проблем с выдачей выбора в этот период времени. Уровень изоляции по умолчанию, ЧТЕНИЕ, ЗАФИКСИРОВАННОЕ, предотвратит грязное чтение, и при 60 вставках в минуту должно работать нормально. msdn.microsoft.com/en-us/library/ms189122.aspx Вы действительно видите проблему на практике или просто планируете заранее?

3. Я просто планирую заранее. В настоящее время у каждого сервера есть своя собственная база данных для записи, однако мы перейдем к одной центральной базе данных, в которую будут записывать все эти серверы. Я ошибся в объеме выполняемых нами вставок, в среднем, в часы пик мы делаем около 250 вставок в минуту. Итак, я не только хочу убедиться, что ВЫБОР не вызовет никаких проблем, у нас будет 7 серверов, выполняющих запись в эту таблицу со скоростью 35 в минуту.

4. Я снова ошибся, но теперь я знаю, что это правильно, поскольку я подтвердил с тем, кто знает. Это будет около 500-600 вставок в минуту.

5. @Antares — Вы все еще хорошо разбираетесь в возможностях SQL Server (я предполагаю, что вы используете Enterprise). Если вы перенесете другие серверы в центральную базу данных и заметите снижение производительности, вы можете начать отслеживать неэффективность использования.

Ответ №2:

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

NOLOCK не создает блокировок строк в запросе, в который вы его добавляете, и не влияет на блокировки, выданные другими запущенными запросами. NOLOCK выдает блокировку Sch-S, блокировку стабильности схемы, которая не вызовет у вас проблем.

Комментарии:

1. Спасибо, поэтому мне нужно будет использовать опцию nolock, но есть ли способ предотвратить появление грязных незафиксированных фрагментов?

Ответ №3:

Я полагаю, вы неправильно поняли. выберите … with (nolock) не получит никаких блокировок. То есть, он не будет блокировать какие-либо другие записи.

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

Комментарии:

1. Хм, значит, нет способа читать только зафиксированные строки, не блокируя таблицу во время выбора?

Ответ №4:

Вы можете использовать NOLOCK, но я бы рекомендовал это только в тех случаях, когда вы знаете, что «грязные данные» допустимы (например, база данных системного журнала, где вы знаете, что данные никогда не будут изменены или удалены после их вставки). Лучший способ сделать это — ВЫБРАТЬ из данных, которые НЕ блокируются; можете ли вы определить строки, на которые не влияет ваша вставка? Например, если ваши данные вставляются с помощью столбца CreateDate, по умолчанию имеющего значение GETDATE() , убедитесь, что ваши запросы извлекают данные ДО этого момента.

Конечно, все зависит от того, сколько данных записывается и генерирует ли оператор insert блокировки строк, страниц или таблиц…

Комментарии:

1. Я полагаю, что это будет ВСТАВКА каждую секунду или около того.

2. Моя ошибка, после выполнения чисел мы в среднем выполняем около 250 вставок в минуту.

Ответ №5:

Один из вариантов, который здесь не обсуждается, — использовать репликацию. Если вы реплицируете соответствующую таблицу и выполняете свои запросы в реплицируемой базе данных, вы не будете блокировать вставки / обновления. (В вашем случае я бы использовал репликацию транзакций — https://msdn.microsoft.com/en-us/library/ms151176.aspx ).