Инструкция ОБНОВЛЕНИЯ при загрузке данных

#sql-server #tsql

#sql-сервер #tsql

Вопрос:

У меня следующий сценарий: я запускаю инструкцию update для таблицы 10M rows, чтобы обновить определенный флаг состояния. Пока инструкция все еще выполняется, в таблицу были введены новые данные. Вопрос в том, повлияет ли обновление на эти новые данные или учитывается только начальный 10M?

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

1. Это зависит от уровня изоляции . Если вы используете NOLOCK или READ UNCOMMITTED (обе плохие идеи), новые записи будут видны. Что вы хотите сделать? Как вы собираетесь изменять 10M строк?

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

3. оба не используются (NOLOCK или READ UNCOMMITTED), поэтому я предполагаю, что новые записи не будут видны. Модификация — это просто установка столбца [Статус] = 1

4. Это не just так, если столбец является bit обновлением, это может заблокировать всю таблицу — нет смысла создавать индекс над bit полем, поскольку 50% строк будут иметь одно значение, а остальные 50% — другое. Таким образом, сервер выполнит полное сканирование таблицы, блокируя всю таблицу. Это может блокировать вставки до тех пор, пока выполняется ОБНОВЛЕНИЕ, или задерживать ОБНОВЛЕНИЕ до завершения всех вставок. В любом случае, это slooow и может заморозить систему. Каковы шансы, что ни одна другая строка в 10M не будет изменена?

5. Вы можете использовать изоляцию моментальных снимков, чтобы избежать блокирования других транзакций. При изоляции моментальных снимков сервер поддерживает исходное состояние измененных строк, поэтому каждая транзакция видит данные такими, какими они были при запуске, но считыватели не блокируют записи, и наоборот. Блокировка происходит только в том случае, если две транзакции пытаются изменить одну и ту же строку. Промежуточные версии хранятся в базе данных tempdb, поэтому, если вам нужно изменить все строки, у вас может получиться 10M временных строк, хранящихся в базе данных tempdb.

Ответ №1:

update -> сначала выбирает строки, которые будут затронуты, блокирует их, чтобы предотвратить любые изменения, затем обновляет эти строки.

вы можете вставлять новые строки без проблем (если нет нарушения ограничений :)).

Любая строка, вставленная после ОБНОВЛЕНИЯ, не будет видна инструкцией UPDATE и, следовательно, они не будут изменены.

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

1. Это зависит от уровня изоляции. Если кто-то использует NOLOCK, будут видны новые строки

2. Обновление каждой строки в таблице также приведет к увеличению блокировки до уровня таблицы

3. Другими словами… это намного сложнее, чем говорится в принятом ответе

4. конечно, но я считаю, что мой охватывает то, что после OP. Уверен, что есть документы 10000 слов о блокировке.

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