Je travaillais juste sur un nouveau système pour reporter certaines opérations en dehors des heures de travail sur l'une de nos bases de données. Je suis venu avec (ce que je pense) un schéma assez simple. J'ai été le premier prototypage sur SQL Server 2005 Express, mais j'ai confirmé le même problème sur 2008 Developer. L'erreur que je reçois est:Problème avec l'affichage indexé dans SQL Server, Erreur 8646
Msg 8646, Niveau 21, État 1, Procédure Annuler, ligne 6 Impossible de trouver l'index entrée dans l'index ID 1, de la table 277576027, dans la base de données 'xxxxxx' . L'index indiqué est endommagé ou il y a un problème avec le plan de mise à jour actuel . Exécutez DBCC CHECKDB ou DBCC CHECKTABLE. Si le problème persiste, contactez le support produit.
Le schéma que je utilise est:
create schema Writeback authorization dbo
create table Deferrals (
ClientID uniqueidentifier not null,
RequestedAt datetime not null,
CompletedAt datetime null,
CancelledAt datetime null,
ResolvedAt as ISNULL(CompletedAt,CancelledAt) persisted,
constraint PK_Writeback_Deferrals PRIMARY KEY (ClientID,RequestedAt) on [PRIMARY],
constraint CK_Writeback_Deferrals_NoTimeTravel CHECK ((RequestedAt <= CompletedAt) AND (RequestedAt <= CancelledAt)),
constraint CK_Writeback_Deferrals_NoSchrodinger CHECK ((CompletedAt is null) or (CancelledAt is null))
/* TODO:FOREIGN KEY */
)
create view Pending with schemabinding as
select
ClientID
from
Writeback.Deferrals
where
ResolvedAt is null
go
alter table Writeback.Deferrals add constraint
DF_Writeback_Deferrals_RequestedAt DEFAULT CURRENT_TIMESTAMP for RequestedAt
go
create unique clustered index PK_Writeback_Pending on Writeback.Pending (ClientID)
go
create procedure Writeback.Defer
@ClientID uniqueidentifier
as
set nocount on
insert into Writeback.Deferrals (ClientID)
select @ClientID
where not exists(select * from Writeback.Pending where ClientID = @ClientID)
go
create procedure Writeback.Cancel
@ClientID uniqueidentifier
as
set nocount on
update
Writeback.Deferrals
set
CancelledAt = CURRENT_TIMESTAMP
where
ClientID = @ClientID and
CompletedAt is null and
CancelledAt is null
go
create procedure Writeback.Complete
@ClientID uniqueidentifier
as
set nocount on
update
Writeback.Deferrals
set
CompletedAt = CURRENT_TIMESTAMP
where
ClientID = @ClientID and
CompletedAt is null and
CancelledAt is null
go
Et le code qui provoque l'erreur est comme suit:
declare @ClientA uniqueidentifier
declare @ClientB uniqueidentifier
select @ClientA = newid(),@ClientB = newid()
select * from Writeback.Pending
exec Writeback.Defer @ClientA
select * from Writeback.Pending
exec Writeback.Defer @ClientB
select * from Writeback.Pending
exec Writeback.Cancel @ClientB --<-- Error being raised here
select * from Writeback.Pending
exec Writeback.Complete @ClientA
select * from Writeback.Pending
select * from Writeback.Deferrals
J'ai vu quelques autres rencontrer de tels problèmes, mais ils semblent avoir des agrégats dans leurs vues (et un message de MS indiquant qu'ils supprimeraient la possibilité de créer de telles vues indexées dans SP 1 2005), ou ils l'ont résolu en appliquant une jointure de fusion dans leur clause de jointure (mais Je n'en ai pas).
Initialement, il n'y avait pas de colonne calculée dans la table Deferrals, et la clause where dans la vue testait séparément les colonnes CompletedAt et CancelledAt pour NULL. Mais j'ai changé à ci-dessus juste pour voir si je pourrais provoquer un comportement différent. Toutes mes options SET sont correctes pour l'utilisation de vues indexées, et si elles ne l'étaient pas, je m'attendrais à une erreur moins violente.
Des idées?
Comme je l'ai indiqué dans mon commentaire à Mladen Prajdic - je peux exécuter les scripts ci-dessus dans une base de données fraîchement créée, et toujours obtenir cette erreur. Si un index pouvait être corrompu rapidement (créer sur une table vide, 2 insertions), alors je serais sérieusement inquiet de la stabilité de SQL Server. En outre, comme indiqué, j'ai trouvé "d'autres" causes en ligne qui font apparaître ce message, et ils ne sont pas réellement la corruption d'index. –