Tenho um banco de dados SQL Server com uma tabela com um gatilho que é executado após a inserção. Se eu inserir duas entradas diretamente, uma após a outra, é importante que a segunda entrada seja inserida somente após o término da execução do gatilho. Posso confiar nisso? Ou posso ter uma condição de corrida problemática em algum momento?
O código do gatilho fica assim:
ALTER TRIGGER [dbo].[TR_MachineState_Desable_OldData_ON_Insert]
ON [dbo].[machine_state]
AFTER INSERT
AS
BEGIN
DECLARE @RowID INT;
DECLARE @Name NVARCHAR(30);
DECLARE @MachineState NVARCHAR(30);
DECLARE @Devicescount INT;
DECLARE @StartedOn DATETIME;
DECLARE @CreateOn DATETIME;
DECLARE @ToolName NVarchar(30);
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
SELECT
@RowID=[RowId]
,@Name= [Name]
,@MachineState=[MachineState]
,@Devicescount=[Devicescount]
,@StartedOn= [StartedOn]
,@CreateOn =[ActionDate]
,@ToolName=[ToolName]
from inserted ;
update [machine_state]
set [IsActive]=0
where [Name] =@Name and ToolName = @ToolName and RowId <> @RowID
update machine_state
set IsActive =1
where RowId=@RowID
END
Como você pode ver, o gatilho garante que apenas a última entrada com o mesmo nome de ferramenta e o mesmo nome seja IsActive
verdadeira.
Oh céus
Você terá um problema muito maior se alguém inserir mais de uma única linha nessa tabela. Seu gatilho terá um tempo de coisas bastante não determinístico.
Mas não, não há garantia de que seu gatilho terá concluído a execução quando outra linha chegar.
Você pode tentar suas inserções em maior simultaneidade com uma ferramenta como SQL Query Stress .
Embora não haja garantia sobre a execução de gatilhos de instruções diferentes, o bloqueio correto deve evitar o surgimento de quaisquer problemas.
Conforme mencionado por outros, você precisa corrigir seu bug gigante onde você não está manipulando múltiplas (ou zero!) linhas corretamente.
Você precisaria de um índice
machine_state (Name, ToolName) INCLUDE (RowId, IsActive)
para que o bloqueio funcionasse corretamente. Você também precisa daquela verificação extra que adicionei para garantir que alguém não tente adicionarName, ToolName
linhas duplicadas de uma só vez, caso contrário, os resultados seriam não determinísticos.Deixando tudo isso de lado, sugiro fortemente que você considere usar Temporal Tables , em vez de tentar lançar sua própria versão não muito boa do mesmo. As tabelas temporais lidam com linhas arquivadas e não ativas automaticamente, então você pode usar uma chave primária normal em
Name, ToolName
.