J'ai deux mises à jour - une verrouille d'abord le CI puis le NCI (sur le statut) car la colonne de statut est également en cours de mise à jour. L'autre possède déjà un verrou U sur le NCI car il sait qu'il change et essaie ensuite d'obtenir un verrou U sur le CI.
Quelle est la manière la plus simple de forcer ces derniers à sérialiser? Il semble étrange d'utiliser un indice de niveau TABLE car il s'agit d'un problème d'indexation interne - il n'y a qu'une seule table impliquée - UPDLOCK, HOLDLOCK s'appliquera-t-il automatiquement à tous les index nécessaires sur cette table et forcera-t-il ainsi à être sérialisé?
Voici les requêtes:
UPDATE htt_action_log
SET status = 'ABORTED', CLOSED = GETUTCDATE()
WHERE transition_uuid = '{F53ADDDA-E46B-4726-66D8-D7B640B66597}'
AND status = 'OPEN';
Ce X verrouille la ligne dans le CI (sur la colonne CREATED), puis tente de verrouiller X sur le NCI qui inclut la colonne d'état.
UPDATE htt_action_log
SET status = 'RUNNING {36082BCD-EB52-4358-E3D3-4D96FD5B9F0F} 1360094342'
WHERE action_uuid = (SELECT TOP 1 action_uuid
FROM htt_action_log
WHERE transition_uuid = '{F53ADDDA-E46B-4726-66D8-D7B640B66597}'
AND status = 'OPEN'
ORDER BY action_seq)
Celui-ci verrouille le même NCI - pour la requête imbriquée, je suppose, puis verrouille le CI pour la mise à jour.
Ainsi, l'ordre produit l'impasse.
La solution la plus simple consiste à forcer les deux requêtes à bloquer complètement - c'est-à-dire à sérialiser. Quelle est la façon la plus simple de forcer cela, il suffit de mettre WITH (UPDLOCK, HOLDLOCK)
les références au tableau (un dans le premier et deux dans le second)?
DDL:
Remarque client a plus d'index sur cette table qui devraient être affectés par cette mise à jour, mais ne sont pas mentionnés dans le graphique de blocage.
CREATE TABLE [dbo].[HTT_ACTION_LOG](
[ACTION_UUID] [varchar](128) NOT NULL,
[TRANSITION_UUID] [varchar](128) NOT NULL,
[STATUS] [varchar](128) NOT NULL,
[CREATED] [datetime] NOT NULL,
[CLOSED] [datetime] NULL,
[ACTION_SEQ] [int] NOT NULL,
[ACTION_TYPE] [varchar](15) NOT NULL,
[ACTION_NAME] [varchar](50) NOT NULL,
[ACTION_RESULT] [varchar](8000) NULL,
[PENDING_SINCE] [datetime] NULL,
[ACTION_SQL] [varchar](8000) NULL,
[ERROR_OK] [int] NULL,
[ERROR_COND] [varchar](2048) NULL,
[RETRY] [varchar](128) NULL,
CONSTRAINT [PK_HTT_ACTION_LOG_1] UNIQUE NONCLUSTERED
(
[ACTION_UUID] ASC
)
)
CREATE CLUSTERED INDEX [IK_HTT_ACTION_LOG_2] ON [dbo].[HTT_ACTION_LOG]
(
[CREATED] ASC
)
CREATE NONCLUSTERED INDEX [IK_HTT_ACTION_LOG_1] ON [dbo].[HTT_ACTION_LOG]
(
[TRANSITION_UUID] ASC,
[STATUS] ASC
)
INCLUDE ( [ACTION_UUID],
[ACTION_SEQ])
CREATE NONCLUSTERED INDEX [IK_HTT_ACTION_LOG_4] ON [dbo].[HTT_ACTION_LOG]
(
[ACTION_UUID] ASC,
[STATUS] ASC
)
CREATE NONCLUSTERED INDEX [missing_index_11438530_11438529_HTT_ACTION_LOG] ON [dbo].[HTT_ACTION_LOG]
(
[TRANSITION_UUID] ASC,
[ACTION_TYPE] ASC
)
INCLUDE ( [ACTION_NAME])
CREATE NONCLUSTERED INDEX [missing_index_7207590_7207589_HTT_ACTION_LOG] ON [dbo].[HTT_ACTION_LOG]
(
[STATUS] ASC
)
INCLUDE ( [CREATED],
[PENDING_SINCE],
[ACTION_NAME])
CREATE NONCLUSTERED INDEX [missing_index_8535421_8535420_HTT_ACTION_LOG] ON [dbo].[HTT_ACTION_LOG]
(
[TRANSITION_UUID] ASC
)
INCLUDE ( [ACTION_UUID],
[STATUS])
ALTER TABLE [dbo].[HTT_ACTION_LOG] SET (LOCK_ESCALATION = AUTO)
ALTER TABLE [dbo].[HTT_ACTION_LOG] WITH CHECK ADD CONSTRAINT [FK_HTT_ACTION_LOG_1] FOREIGN KEY([TRANSITION_UUID])
REFERENCES [dbo].[HTT_TRANSITION_LOG] ([TRANSITION_UUID])
ALTER TABLE [dbo].[HTT_ACTION_LOG] CHECK CONSTRAINT [FK_HTT_ACTION_LOG_1]
ALTER TABLE [dbo].[HTT_ACTION_LOG] ADD DEFAULT ('OPEN') FOR [STATUS]
ALTER TABLE [dbo].[HTT_ACTION_LOG] ADD DEFAULT (getutcdate()) FOR [CREATED]
ALTER TABLE [dbo].[HTT_ACTION_LOG] ADD DEFAULT ((0)) FOR [ERROR_OK]