2009-07-03 3 views
0

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?

+0

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. –

Répondre

0

J'ai réussi à trouver la cause de cette erreur, en essayant de construire ce script, à partir de zéro, en ajoutant des morceaux au fur et à mesure.

C'est une sorte de bogue qui est produit si la vue est créée dans le cadre d'une instruction CREATE SCHEMA. Si je sépare le SCHEMA CREATE dans son propre lot, puis que je crée la table et la vue dans des lots séparés, tout fonctionne correctement.


modifier Attendu depuis longtemps - j'ai soulevé sur Connect here. Il a été confirmé que cela posait un problème dans SQL Server 2008.

Les versions internes (en 2010) indiquaient que ce n'était plus un problème, et j'ai confirmé (tout juste en 2016) que le script de la question ne générait pas le problème. même erreur dans SQL Server 2012. Le correctif n'était pas back-porté vers SQL Server 2008.

0

vous avez une corruption d'index. exécutez checkdb et voyez quelles erreurs il vous donne. la chose la plus simple que vous pourriez faire est de reconstruire vos index.

également jeter un oeil à ce KB article s'il s'applique à votre situation.

Notez également que la mise en place d'une clé primaire sur une colonne GUID créera un index clusterisé, ce qui représente la pire performance possible.

+0

Corruption d'index - dans une base de données/schéma/index que j'ai créé il y a 10 minutes, spécifiquement pour ce prototypage? (Aussi, répétable dans la nouvelle base de données) Aussi, oui, conscient de toutes sortes de problèmes avec l'utilisation des GUID. Mais c'est ce que je suis coincé dans cette base de données. Les guids réels pour les clients sont réellement générés avec newsequentialid(). Pas inquiet de la performance pour le moment. –

+0

J'ai déjà modifié les scripts ci-dessus pour utiliser int à la place de uniqueidentifier, et obtenir la même erreur, donc ce n'est pas lié à ce problème –

Questions connexes