Ho una tabella elaborata contemporaneamente da N thread.Seleziona query salta i record durante gli aggiornamenti simultanei
CREATE TABLE [dbo].[Jobs]
(
[Id] BIGINT NOT NULL CONSTRAINT [PK_Jobs] PRIMARY KEY IDENTITY,
[Data] VARBINARY(MAX) NOT NULL,
[CreationTimestamp] DATETIME2(7) NOT NULL,
[Type] INT NOT NULL,
[ModificationTimestamp] DATETIME2(7) NOT NULL,
[State] INT NOT NULL,
[RowVersion] ROWVERSION NOT NULL,
[Activity] INT NULL,
[Parent_Id] BIGINT NULL
)
GO
CREATE NONCLUSTERED INDEX [IX_Jobs_Type_State_RowVersion] ON [dbo].[Jobs]([Type], [State], [RowVersion] ASC) WHERE ([State] <> 100)
GO
CREATE NONCLUSTERED INDEX [IX_Jobs_Parent_Id_State] ON [dbo].[Jobs]([Parent_Id], [State] ASC)
GO
lavoro sta aggiungendo a tavola con State=0 (New)
- può essere consumato da tutti i lavoratori in questo stato. Quando il lavoratore ottiene questo articolo in coda, State
è cambiato in 50 (Processing)
e il lavoro non è più disponibile per altri utenti (gli operatori chiamano [dbo].[Jobs_GetFirstByType]
con argomenti: Type=any, @CurrentState=0, @NewState=50
).
CREATE PROCEDURE [dbo].[Jobs_GetFirstByType]
@Type INT,
@CurrentState INT,
@NewState INT
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DECLARE @JobId BIGINT;
BEGIN TRAN
SELECT TOP(1)
@JobId = Id
FROM [dbo].[Jobs] WITH (UPDLOCK, READPAST)
WHERE [Type] = @Type AND [State] = @CurrentState
ORDER BY [RowVersion];
UPDATE [dbo].[Jobs]
SET [State] = @NewState,
[ModificationTimestamp] = SYSUTCDATETIME()
OUTPUT INSERTED.[Id]
,INSERTED.[RowVersion]
,INSERTED.[Data]
,INSERTED.[Type]
,INSERTED.[State]
,INSERTED.[Activity]
WHERE [Id] = @JobId;
COMMIT TRAN
END
Dopo l'elaborazione, lavoro State
può essere modificato in 0 (New)
nuovamente o può essere una volta impostato 100 (Completed)
.
CREATE PROCEDURE [dbo].[Jobs_UpdateStatus]
@Id BIGINT,
@State INT,
@Activity INT
AS
BEGIN
UPDATE j
SET j.[State] = @State,
j.[Activity] = @Activity,
j.[ModificationTimestamp] = SYSUTCDATETIME()
OUTPUT INSERTED.[Id], INSERTED.[RowVersion]
FROM [dbo].[Jobs] j
WHERE j.[Id] = @Id;
END
Jobs ha struttura gerarchica, lavoro genitore ottiene State=100 (Completed)
solo quando tutti bambino sono stati completati. Alcuni operatori chiamano stored procedure ([dbo].[Jobs_GetCountWithExcludedState]
con @ExcludedState=100
) che restituiscono il numero di lavori incompleti, quando restituisce 0, il processo padre State
può essere impostato su 100 (Completed)
.
CREATE PROCEDURE [dbo].[Jobs_GetCountWithExcludedState]
@ParentId INT,
@ExcludedState INT
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT COUNT(1)
FROM [dbo].[Jobs]
WHERE [Parent_Id] = @ParentId
AND [State] <> @ExcludedState
END
Il problema principale è uno strano comportamento di questa stored procedure. A volte restituisce 0 per lavoro principale, ma è esattamente ha lavori incompleti. Ho provato ad attivare la modifica del tracciamento dei dati e alcune informazioni di debug (inclusa la creazione di profili) - lavori secondari 100% non ha State=100
quando SP restituisce 0. Sembra che l'SP salti i record, che non sono nello stato 100 (Completed)
, ma perché succede e come possiamo impedirlo?
UPD: Calling [dbo].[Jobs_GetCountWithExcludedState]
inizia quando lavoro genitore ha bambino. Non ci сan sarà alcuna situazione in cui lavoratore inizia a controllare i processi secondari senza la loro esistenza, perché la creazione di Childs e l'impostazione di lavoro genitore controllare l'attività avvolto in transazione:
using (var ts = new TransactionScope())
{
_jobManager.AddChilds(parentJob);
parentJob.State = 0;
parentJob.Activity = 30; // in this activity worker starts checking child jobs
ts.Complete();
}
questo acaro aiuta il tuo problema http://stackoverflow.com/questions/12608780/understanding-sql -server-lock-on-select-query –
e questo http://vladmihalcea.com/2014/09/14/a-beginners-guide-to-database-locking-and-the-lost-update-phenomena/ –
Ho trovato questo BLOCCO SERVER SQL: http://stackoverflow.com/questions/12608780/understanding-sql-server-locks-on-select-queries http: // vladmihalcea.com/2014/09/14/a-principianti-guida-al-database-blocco-e-lost-update-phenomena/ –