#sql #sql-server #tsql #nolock
Вопрос:
Предположим, у меня есть следующий запрос в двух отдельных окнах запросов SSMS:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRANSACTION
UPDATE dbo.Jobs
SET [status] = 'Running'
OUTPUT Inserted.*
WHERE [status] = 'Waiting'
--I'm NOT committing yet
--Commit Transaction
Я запускаю окно запроса 1 (но не фиксирую), а затем запускаю окно запроса 2.
Я хочу, чтобы в окне запроса 2 немедленно обновлялись только строки, которые были вставлены после того, как я запустил запрос 1 (все новые записи поступают со статусом «Ожидание»). Однако SQL Server ожидает завершения первого запроса, потому что в инструкции update он не считывает грязные значения (даже если он настроен на ЧТЕНИЕ НЕЗАФИКСИРОВАННЫХ).;
Есть ли способ преодолеть это?
В моем приложении у меня будет 2 (или более) запущенных процесса, я хочу, чтобы процесс 2 мог получать строки, которые процесс 1 не получил; Я не хочу, чтобы процесс 2 должен был ждать завершения процесса 1
Комментарии:
1. В моем приложении у меня будет 2 (или более) запущенных процесса, я хочу, чтобы процесс 2 мог получать строки, которые процесс 1 не получил; Я не хочу, чтобы процесс 2 должен был ждать завершения процесса 1
2. Какова мощность столбца состояния, сколько строк, вероятно, будет в любом состоянии?
3. вероятно, это начнется с 50 в каждом статусе; со временем их станет больше
4. Я не верю, что вы хотите
read uncommitted
здесь, вам просто нужно пропустить строки, уже заблокированные транзакцией, что вы можете сделать с помощьюwith(readpast)
подсказки5. Решение, вероятно, состоит в том, чтобы стать БОЛЕЕ строгим, а не менее, и убедиться, что каждая операция длится как можно дольше. Это может означать разбиение существующих длительных заданий на более мелкие идемпотентные этапы.
Ответ №1:
То, о чем вы просите, просто невозможно.
Даже на самом низком уровне изоляции READ UNCOMMITTED
(aka NOLOCK
), X-Lock
(эксклюзивный) должен быть принят для внесения изменений. Другими словами, записи всегда блокируются, даже если операции чтения, которые извлекли эти строки, не были заблокированы.
Таким образом, даже несмотря на то , что сеанс 2 READ UNCOMMITTED
также выполняется, если он хочет внести изменения, он также должен принять X-Lock
, что несовместимо с первой X-блокировкой.
Решение здесь состоит в том, чтобы либо сделать это за один сеанс, либо зафиксировать немедленно. в любом случае, не удерживайте блокировки в течение какого-либо периода времени, так как это может привести к массивным цепочкам блокировки и даже тупикам.
Если вы хотите просто игнорировать все те строки, которые были вставлены, вы можете воспользоваться WITH (READPAST)
подсказкой.
READ UNCOMMITTED
как уровень изоляции или как подсказка имеет огромные проблемы.
Это может привести к чему угодно, от тупиков до совершенно неправильных результатов. Например, вы можете прочитать строку дважды или вообще не читать, когда по логическому определению схемы должна была быть ровно одна строка. Вы можете прочитать целые страницы дважды или вообще не читать.
Вы можете попасть в тупик из U-Lock
-за того, что вы не принимаете UPDATE
заявления и DELETE
заявления.
И вы по-прежнему блокируете схему, так что вы все равно можете застрять за синхронным обновлением статистики или перестройкой индекса.