У меня есть таблица, которая содержит данные о событиях в моем приложении, и я хочу обрабатывать эти события по порядку, по одному за раз. Строки создаются (вставляются в таблицу) из триггера на другой таблице. Строки выбираются для обработки с использованием запроса в стиле UPDATE TOP 1 ... ORDER BY Id. Здравый смысл говорит, что строка должна быть создана до того, как она может быть выбрана, но во время нагрузочного тестирования очень редко дата и время, записанные для комплектации, ДО ДО даты, записанной для создания. относительно того, что происходит (основано главным образом на блоге из Коннор Каннингем связан с Использование функции в предложении where: сколько раз оценивается функция? ) - это выполнение create и запросы на выбор перекрываются, и sysutcdatetime () оценивается в start выполнения запроса, прежде чем ожидания приведут к завершению запросов sh в обратном порядке, в котором они были запущены. Примерно так (время движется вниз)
---------------------------------------------------
|Create Query |Pick Query |
===================================================
| |query start |
---------------------------------------------------
| |evaluate sysutcdatetime |
---------------------------------------------------
|query start |wait/block |
---------------------------------------------------
|evaluate sysutcdatetime |wait/block |
---------------------------------------------------
|insert rows using |wait/block |
|sysutcdatetime value | |
|as Create timestamp | |
---------------------------------------------------
|transaction commits |wait/block |
---------------------------------------------------
| |update top 1 using |
| |sysutcdatetime value as |
| |Pick timestamp |
---------------------------------------------------
Может кто-нибудь подтвердить, когда оцениваются постоянные функции времени выполнения? Или предоставьте альтернативное объяснение того, как дата и время, записанные для комплектации, могут быть ДО даты, записанной для создания?
Просто чтобы прояснить ситуацию, я хочу понять поведение, которое я вижу, а не способы изменить мою схему / код, чтобы устранить проблему go. Мое исправление на данный момент состоит в том, чтобы удалить ограничение проверки (PickedAt >= CreatedAt)
.
Для полноты, соответствующие части моей таблицы событий:
create table dbo.JobInstanceEvent (
Id int identity not null constraint PK_JobInstanceEvent primary key,
JobInstanceId int not null constraint FK_JobInstanceEvent_JobInstance foreign key references dbo.JobInstance (Id),
JobInstanceStateCodeOld char(4) not null constraint FK_JobInstanceEvent_JobInstanceState1 foreign key references ref.JobInstanceState (Code),
JobInstanceStateCodeNew char(4) not null constraint FK_JobInstanceEvent_JobInstanceState2 foreign key references ref.JobInstanceState (Code),
JobInstanceEventStateCode char(4) not null constraint FK_JobInstance_JobInstanceEventState foreign key references ref.JobInstanceEventState (Code),
CreatedAt datetime2 not null,
PickedAt datetime2 null,
FinishedAt datetime2 null,
constraint CK_JobInstanceEvent_PickedAt check (PickedAt >= CreatedAt),
constraint CK_JobInstanceEvent_FinishedAt check (FinishedAt >= PickedAt),
constraint CK_JobInstanceEvent_PickedAt_FinishedAt check (PickedAt is null and FinishedAt is null or
PickedAt is not null) -- this covers the allowable combinations of PickedAt/FinishedAt
)
Оператор SQL, который создает новые строки:
insert dbo.JobInstanceEvent (JobInstanceId, JobInstanceStateCodeOld, JobInstanceStateCodeNew, JobInstanceEventStateCode, CreatedAt)
select
i.Id as JobInstanceId,
d.JobInstanceStateCode as JobInstanceStateCodeOld,
i.JobInstanceStateCode as JobInstanceStateCodeNew,
'CRTD' as JobInstanceEventStateCode,
sysutcdatetime() as CreatedAt
from
inserted i
inner join deleted d on d.Id = i.Id
where
i.JobInstanceStateCode <> d.JobInstanceStateCode and -- the state has changed and
i.JobInstanceStateCode in ('SUCC', 'FAIL') -- the new state is either success or failure.
Оператор SQL, который выбирает строку:
; with cte as (
select top 1
jie.Id,
jie.JobInstanceId,
jie.JobInstanceStateCodeOld,
jie.JobInstanceStateCodeNew,
jie.JobInstanceEventStateCode,
jie.PickedAt
from
dbo.JobInstanceEvent jie
where
jie.JobInstanceEventStateCode = 'CRTD'
order by
jie.Id
)
update cte set
JobInstanceEventStateCode = 'PICK',
PickedAt = sysutcdatetime()
output
inserted.Id,
inserted.JobInstanceId,
inserted.JobInstanceStateCodeOld,
inserted.JobInstanceStateCodeNew
into
@PickedJobInstanceEvent
Я использую SQL Server 2016, но я не думаю, это спецификация версии c проблема.