@artshelom

Как не блокировать соседние записи для обновления добавив триггер?

Create trigger Update_applicationUpdate_MainTab on MainTab
after update
NOT FOR REPLICATION
as 
begin
	Update [SubTab] with(ROWLOCK) set [LatUpdateTime] = SYSDATETIME() 
	where [dbo].[SubTab].[ClientTableId] in (select Id from inserted)
end;

При добавлении данного триггера, когда делаю: из первой транзакции обновление первой строчки (id=1) (не завершая транзакцию). А из второй транзакции, обновление второй строчки(id=2), то пока первая строчка не обновиться (не закончиться транзакция). Вторая транзакция, не сработает. Без данного триггера, все работает как надо.
А именно: Из первой транзакции обновляю первую строчку. Из второй вторую строчку. И вторая успешно выполняется.
В чем может быть причина? (В SubTab - к каждой строчке MainSub привязана своя строчка SubTab. То есть там они не совпадают). Как я понимаю, потому что inserted - может накапливаться, несколько данных за прошлую транзакцию?

CREATE TABLE [dbo].[SubTable](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Table] [nvarchar](64) NULL,
	[LatUpdateTime] [datetime2](7) NULL,
	[ClientTableId] [nvarchar](64) NULL,
 CONSTRAINT [PK_SubTable] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[MainTable](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Name] [nvarchar](max) NOT NULL
 CONSTRAINT [PK_MainTable] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

insert into [dbo].[MainTable] VALUES('check1')
insert into [dbo].[MainTable] VALUES('check2')
insert into [dbo].[SubTable] VALUES('[dbo].[MainTable]', SYSDATETIME(), SYSDATETIME(), 1)
insert into [dbo].[SubTable] VALUES('[dbo].[MainTable]', SYSDATETIME(), SYSDATETIME(), 2)

Create trigger Update_applicationUpdate_MainTable on MainTable 
after update 
as
Update [SubTable] with(ROWLOCK) set [LatUpdateTime] = SYSDATETIME() 
	where [dbo].[SubTable].[ClientTableId] in (select Id from inserted) 
	and [Table] = '[dbo].[MainTable]';


Транзакция -1:
begin transaction

update [dbo].[MainTable]
	set [Name] = 'Тестовый37' where id = 1


Транзакция-2:
update [dbo].[MainTable]
	with(ROWLOCK)
	set [Name] = 'Тестовый37' where id = 2
  • Вопрос задан
  • 129 просмотров
Пригласить эксперта
Ответы на вопрос 1
unfilled
@unfilled
Предполагаю, что проблема в том, что:
  1. колонка [ClientTableId] в дочерней таблице не индексирована, соответственно, каждое срабатывание триггера вычитывает всю таблицу
  2. у [ClientTableId] тип nvarchar, который не совпадает с типом колонки Id в родительской таблице, поэтому при каждом срабатывании триггера, требуется преобразование типа nvarchar к int, что "отключит" возможность использования индекса, даже при его наличии
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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