Когда я обновляю/вставляю одну строку, она должна заблокировать всю таблицу?

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

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

Два вопроса:

  1. Когда я обновляю/вставляю одну строку, она блокирует всю таблицу?
  2. Что может быть сделано для работы вокруг этого вида проблемы?
26
задан KM. 11 February 2010 в 22:11
поделиться

4 ответа

Можно также убедиться, что вся страница хранится в переменной, и вся эта обработка выполняется в тегах cfsilent. Например,

<cfsilent>
    <!-- some coldfusion -->
    <cfsavecontent variable="pageContent">
        <html>
            <!-- some content -->
        </html>
    </cfsavecontent>
    <!-- reformat pageContent if required -->
</cfsilent><cfoutput>#pageContent#</cfoutput>

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

-121--2583153-

Необходимо использовать HTML Agility Pack .

Например:

var doc = new HtmlWeb().Load(url);
var linkTags = doc.DocumentNode.Descendants("link");
var linkedPages = doc.DocumentNode.Descendants("a")
                                  .Select(a => a.GetAttributeValue("href", null))
                                  .Where(u => !String.IsNullOrEmpty(u));
-121--1201207-

Обычно нет, но это зависит (чаще всего используется ответ для SQL Server!)

SQL Server придется каким-то образом заблокировать данные, участвующие в транзакции. Он должен блокировать данные в самой таблице, а данные - все затронутые индексы, пока выполняется изменение. Чтобы улучшить параллелизм, существует несколько "грануляций" блокировки, которые сервер может решить использовать, чтобы разрешить выполнение нескольких процессов: блокировки строк, блокировки страниц и блокировки таблиц являются общими (их больше). Уровень блокировки зависит от того, как сервер решит выполнить данное обновление. Усложняющие вещи, также существуют классификации блокировок, такие как общие, исключительные и намеренные исключительные, которые управляют тем, можно ли считать и/или изменять заблокированный объект.

Мой опыт показывает, что SQL Server в основном использует блокировки страниц для изменений в небольших частях таблиц и после некоторого порогового значения автоматически перерастет в блокировку таблицы, если большая часть таблицы кажется (из статистики) затронутой обновлением или удалением. Идея в том, что быстрее заблокировать таблицу (одну блокировку), чем получить и управлять тысячами отдельных блокировок строк или страниц для большого обновления.

Чтобы увидеть, что происходит в вашем конкретном случае, вам нужно посмотреть логику запроса и, пока ваши материалы работают, изучить условия блокировки/блокировки в sys.dm_tran_locks, sys.dm_os_waiting_tasks или других DMV. Вы бы хотели узнать, что именно блокируется на каком шаге в каждом из ваших процессов, чтобы выяснить, почему один блокирует другой.

22
ответ дан 28 November 2019 в 06:58
поделиться

Краткая версия:

  1. Нет
  2. Исправьте код.

Полная версия:

LCK_M_IX - это блокировка намерения, означающая, что операция установит блокировку X на подчиненный элемент. Например. При обновлении строки в таблице операционная таблица принимает блокировку IX для таблицы перед блокировкой X строки, которая обновляется / вставляется / удаляется. Блокировки намерений являются распространенной стратегией для работы с иерархиями, такими как таблица / страница / строка, потому что диспетчер блокировок не может понять физическую структуру ресурсов, запрошенных для блокировки (т. Е. Он не может знать, что X-блокировка на странице P1 несовместима с S-блокировка строки R1, поскольку R1 содержится в P1). Для получения дополнительной информации см. Режимы блокировки .

Тот факт, что вы видите состязание в блокировках с намерением, означает, что вы пытаетесь получить блокировки объектов высокого уровня, например блокировки таблиц. Вам нужно будет проанализировать исходный код на предмет блокируемого запроса (тот, который запрашивает блокировку, несовместимую с LCK_M_IX) и устранить причину запроса блокировки на уровне объекта. Что это означает, будет зависеть от вашего исходного кода, я не знаю, что вы там делаете. Я предполагаю, что вы используете ошибочную подсказку о блокировке.

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

20
ответ дан 28 November 2019 в 06:58
поделиться

Различные базы данных имеют разные механизмы блокировки, но такие, как SQL Server и Oracle, имеют разные типы блокировки.

По умолчанию в SQL Server используется пессимистическая блокировка страниц, поэтому, если у вас небольшое количество записей, все они могут быть заблокированы.

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

1
ответ дан 28 November 2019 в 06:58
поделиться

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

Выясните, что делает каждый запрос, и получаете ли вы эскалацию блокировок, которой вы не ожидали. То, что вы говорите WITH (ROWLOCK) в запросе, не означает, что SQL Server сможет выполнить ... если вы коснулись нескольких индексов, индексированных представлений, постоянных вычисляемых столбцов и т. Д., Тогда есть все виды причин, по которым ваша блокировка строк может не выдерживать никакой критики. У вас также могут быть вещи позже в транзакции, которые занимают больше времени, чем вы думаете, и, возможно, вы не понимаете, что блокировки всех объектов, участвующих в транзакции (а не только выполняемого в данный момент оператора), могут удерживаться в течение продолжительность транзакции.

11
ответ дан 28 November 2019 в 06:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: