2015-12-24 5 views
1

У меня есть быстрый вопрос для вас ... Если бы я побежал следующую команду:будет удалить из внутренней операции удаления записей из после операции

BEGIN TRANSACTION 
<commands...> 
DELETE FROM <table> 
COMMIT TRANSACTION 

И в то время как выше транзакция выполняется вставка осуществляется на стол. Будет ли удаление:

  1. удалить данные добавлены после того, как транзакция началась
  2. только удалить данные, которые существовали в начале сделки или которая была добавлена ​​в качестве части сделки

Надежда кто-то может Помогите.

+0

Ответ на ваш вопрос зависит от уровня изоляции вашей транзакции. –

+0

Прочитанный уровень изоляции – denimknight

ответ

2

Я предполагаю, что ваш код работает в одном SPID, и вставка будет работать на другом SPID, а уровень изоляции по умолчанию используется в SQL SERVER - READ COMMITTED.

Вскоре ответ НЕТ, так как INSERT будет ждать окончания DELETE. Испытано как это:

1) Настройка:

-- drop table dbo.Test 
CREATE TABLE dbo.Test 
(
    Id INT NOT NULL, 
    Value NVARCHAR(4000) 
) 
GO 

INSERT INTO Test (Id, Value) 
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)), text 
from sys.messages 
GO 

2) В окне запроса 1

BEGIN TRANSACTION 
DELETE FROM dbo.Test where ID > 100000 

3) В окне запроса 2

INSERT INTO Test (Id, Value) 
SELECT 100000000 + ROW_NUMBER() OVER (ORDER BY (SELECT 1)), text 
from sys.messages 

sp_who2 active показывает, что второй запрос (SPID) блокируется первым запросом, поэтому запрос ожидает получения блокировки

3) В окне запроса 1

COMMIT -- query 1 will finish 

4) Второй запрос завершится

Таким образом, INSERT должен ждать, пока DELETE заканчивается.

+0

Это замечательно.Спасибо за информацию/ – denimknight

+2

Этот ответ неверный. Этот INSERT использует SELECT в качестве источника, и поскольку он использует SELECT, он будет использовать Shared locks для чтения, так что это причина, по которой INSERT ждет. И еще, этот пример предполагает, что таблица не имеет первичного ключа, поэтому вся таблица будет заблокирована для операции удаления, и это неверно для более общей таблицы событий с Первичным ключом. –

+0

Как я понял, denimknight хочет знать, может ли INSERT вводить данные, в то время как DELETE происходит. Как указано в документах MS для DELETE, он блокирует таблицу: по умолчанию оператор DELETE всегда получает исключающую (X) блокировку в изменяемой таблице и удерживает эту блокировку до завершения транзакции. С исключительной (X) блокировкой никакие другие транзакции не могут изменять данные; операции чтения могут выполняться только с использованием подсказки NOLOCK или чтения незафиксированного уровня изоляции. (https://msdn.microsoft.com/en-us/library/ms189835.aspx - Поведение блокировки) – Alexei

0
  1. Да. Почему нет? Если другие запросы в вашей транзакции не будут содержать блокировки в вашей таблице, SQL Server начнет блокировать вашу таблицу с блокировками обновлений сразу после запуска операции DELETE. Таким образом, перед этим действием все другие процессы могут успешно добавлять новые строки в таблицу.
  2. DELETE в вашем случае удалит все зафиксированные данные, существовавшие в вашей таблице до операции DELETE. Исключенные данные этой транзакции также будут удалены.
2

Вам нужно больше погрузиться в тему «Замки и уровни изоляции транзакций». Посмотрите на этот пример, который может быть более распространенным, чем в предыдущем ответе. INSERT здесь не блокируется, потому что DELETE просто блокирует набор ключей для операции DELETE.

И все же, перед запуском операции DELETE, если другие запросы в этой транзакции не содержат блокировок в этой таблице, нет причин для SQL Server предотвращать операции INSERT из другой транзакции.

CREATE TABLE t (Id int PRIMARY KEY) 
GO 

INSERT INTO t VALUES(1) 
GO 

BEGIN TRAN 

DELETE FROM t 

-- separate window 
INSERT INTO t VALUES(2)