2009-07-03 13 views
0

Ich war gerade dabei, ein neues System für das Zurückstellen bestimmter Operationen bis zu außerhalb der Stunden in einer unserer Datenbanken zu prototypieren. Ich habe (was ich denke) ein ziemlich einfaches Schema entwickelt. Ich habe das erste Mal mit SQL Server 2005 Express prototypisiert, habe aber das gleiche Problem für den Entwickler 2008 behoben. Der Fehler Ich erhalte ist:Problem mit der indizierten Sicht in SQL Server, Fehler 8646

Msg 8646, Ebene 21, Status 1, Verfahren abbrechen, Line 6 Kann nicht Index Eintrag in Index-ID 1 der Tabelle 277.576.027, in der Datenbank 'xxxxxx' finden . Der angezeigte Index ist beschädigt oder es gibt ein Problem mit dem aktuellen Update Plan. Führen Sie DBCC CHECKDB oder DBCC CHECKTABLE aus. Wenn das Problem weiterhin besteht, wenden Sie sich an den Produkt-Support.

Das Schema Ich verwende ist:

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 

Und der Code, der Fehler provoziert wie folgt:

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 

Ich habe zu begegnen solche Probleme ein paar andere gesehen, aber sie scheinen entweder Aggregate in ihren Ansichten zu haben (und eine Nachricht von MS, dass sie die Möglichkeit zum Erstellen solcher indizierten Ansichten in 2005 SP 1 entfernen würden), oder sie lösten sie, indem sie einen Merge-Join in ihrer Join-Klausel anwendeten (aber Ich habe keins).

Anfänglich gab es in der Tabelle Deferrals keine berechnete Spalte, und die WHERE-Klausel in der Ansicht prüfte die Spalten CompletedAt und CanceledAt für NULL separat. Aber ich wechselte zu den oben genannten, nur um zu sehen, ob ich anderes Verhalten provozieren könnte.

Alle meine SET-Optionen sind für die Verwendung indizierter Ansichten geeignet, und wenn nicht, würde ich erwarten, dass ein weniger gewaltsamer Fehler ausgelöst wird.

Irgendwelche Ideen?

+0

Wie ich in meinem Kommentar zu Mladen Prajdic angegeben habe - ich kann die oben genannten Skripte in einer frisch erstellten Datenbank ausführen, und immer noch diesen Fehler erhalten. Wenn ein Index so schnell beschädigt werden könnte (Erstellen auf einer leeren Tabelle, 2 Einfügungen), wäre ich ernsthaft besorgt über die Stabilität von SQL Server. Wie bereits erwähnt, habe ich "andere" Online-Ursachen gefunden, die diese Nachricht hervorbringen, und sie sind nicht wirklich eine Indexbeschädigung. –

Antwort

0

Ich habe es geschafft, herauszufinden, was diesen Fehler verursacht, indem ich versuche, dieses Skript von Grund auf neu aufzubauen, indem ich Teile hinzufüge.

Es ist eine Art von Fehler, der erzeugt wird, wenn die Ansicht als Teil einer CREATE SCHEMA-Anweisung erstellt wird. Wenn ich das CREATE SCHEMA in seinen eigenen Stapel aufteile und dann die Tabelle und die Ansicht in getrennten Stapeln erstelle, funktioniert alles gut.


Lange überfällig bearbeiten - ich hob diese auf Connect here. Es wurde als ein Problem in SQL Server 2008 bestätigt.

Interne Builds (im Jahr 2010) angegeben, dass es kein Problem mehr war, und ich habe (gerade jetzt, 2016) bestätigt, dass das Skript in der Frage nicht erzeugt Derselbe Fehler in SQL Server 2012. Der Fix wurde nicht zurück zu SQL Server 2008 portiert.

0

Sie haben Index Korruption. Führen Sie checkdb aus und sehen Sie, welche Fehler es Ihnen gibt. Am einfachsten können Sie Ihre Indizes neu erstellen.

Werfen Sie einen Blick auf diese KB article, wenn es für Ihre Situation gilt.

Beachten Sie auch, dass wenn Sie einen Primärschlüssel auf eine GUID-Spalte setzen, wird ein geclusterter Index darauf erstellt, was das Schlimmste ist, was Sie bei der Leistung erreichen könnten.

+0

Index Korruption - in einer Datenbank/Schema/Index, die ich vor 10 Minuten speziell für dieses Prototyping erstellt? (Auch wiederholbar in der neuen Datenbank) Auch, ja, aller Arten von Problemen mit der Verwendung von GUIDs bewusst. Aber das ist es, woran ich in dieser Datenbank festhalte. Die tatsächlichen Guids für Clients werden tatsächlich mit newsequentialid() generiert. Im Moment nicht um die Leistung besorgt. –

+0

Ich habe gerade die oben genannten Skripts geändert, um Int anstelle von Uniqueidentifier zu verwenden, und den gleichen Fehler erhalten, so dass es nicht mit diesem Problem verbunden ist –