Как заблокировать вставки в SQL Server от одного и того же пользователя - сериализуемая изоляция - PullRequest
0 голосов
/ 28 сентября 2011

У меня есть следующая таблица

CREATE TABLE [dbo].[Test]([Id] [int] NOT NULL,[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
[Id] ASC
)
WITH (PAD_INDEX = OFF, 
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY=OFF,
ALLOW_ROW_LOCKS=ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE NONCLUSTERED INDEX [IX_Test] ON [dbo].[Test] 
(
   [Name] ASC
)
WITH (PAD_INDEX  = OFF, 
STATISTICS_NORECOMPUTE  = OFF, 
SORT_IN_TEMPDB = OFF, 
IGNORE_DUP_KEY = OFF, 
DROP_EXISTING = OFF, 
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

Теперь я хочу запретить вставки одного и того же пользователя (но другого сеанса), пока не завершится сеанс.Например, если пользователь Джон начинает сеанс со вставкой, я хочу, чтобы его другой сеанс (тоже со вставкой) был заблокирован до завершения первого сеанса.Другими словами, мне нужно заблокировать вставки, которые еще не существуют.

Поэтому я создал следующие два сценария для их запуска в отдельных окнах запросов Management Studio: Первый (пользователь Джон; waitfor находится в первом запросе только длябыть в состоянии смоделировать проблему):

begin tran

select COUNT(*)
from Test with(updlock,holdlock)
where Name = 'John'

waitfor delay '00:00:05'

insert into Test(Id,Name)
select isnull(MAX(Id) + 1,1),'John' from Test

commit tran

Секунда (пользователь Питер):

begin tran

select COUNT(*)
from Test with(updlock,holdlock)
where Name = 'Peter'

insert into Test(Id,Name)
select isnull(MAX(Id) + 1,1),'Peter' from Test

commit tran

Теперь, если я запускаю первый запрос из первого окна запроса Management Studio, а затем запускаю второй запросво втором окне запроса до того, как первый завершен, второй запрос блокируется, пока первый не завершится.Ну, может быть, это то, как это должно работать, но это не то, чего я хочу: я хочу, чтобы второй сеанс был заблокирован, только если тот же пользователь хочет вставить данные.В моем примере Джон начинает вставлять данные, но Питер (второй запрос) блокируется до тех пор, пока не завершится вставка Джона.

Можно ли указать серверу sql (с подсказками блокировки, я полагаю) блокировать второй запрос, только еслитот же пользователь пытается вставить данные?Например, если Джон начинает вставлять данные, чтобы блокировать только другие сеансы Джона, но не сеансы Питера?

1 Ответ

0 голосов
/ 28 сентября 2011

В этом случае вам, вероятно, нужно установить флаг в БД, который зависит от пользователя (создайте таблицу с user_id и флагом is_writting).Когда вы начинаете запись в таблицу, сначала проверьте, установлен ли флаг, - при этом не обновляйте флаг и не пишите в таблицу.После того как запись завершена, снимите флажок.

Вот как я, вероятно, решил бы это.Но я открыт для любых других способов;)

...