2009-07-03 79 views
0

我只是原型化一個新系統,用於推遲某些操作,直到某個數據庫超時。我想出了(我認爲)一個非常簡單的模式。我第一次在SQL Server 2005 Express上進行原型設計,但是在2008 Developer上確認了同樣的問題。我得到的錯誤是:SQL Server中的索引視圖有問題,錯誤8646

消息8646,級別21,狀態1,過程 取消,6號線無法找到索引ID 1指數 項,表 277576027的,在數據​​庫 'XXXXXX' 。 指示索引已損壞或存在 與當前更新 計劃有關的問題。運行DBCC CHECKDB或DBCC CHECKTABLE。如果問題仍然存在,請致電 聯繫產品支持。

我使用的模式是:

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 

這引發了錯誤如下代碼:

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 

我見過幾個人遇到這樣的問題,但他們似乎在他們的觀點中有彙總(並且MS的消息表示他們將刪除在2005 SP 1中創建此類索引視圖的能力),或者他們通過在其聯接子句中應用合併聯接來解決此問題(但我沒有一個)。

最初在Deferrals表中沒有計算列,而視圖中的where子句分別爲NULL測試了CompletedAt和CancelledAt列。但我改變了上面的看法,只是爲了看看我能否挑起不同的行爲。

我所有的SET選項看起來都適合使用索引視圖,如果它們不是,我希望拋出一個不太暴力的錯誤。

任何想法?

+0

正如我在對Mladen Prajdic的評論中指出的 - 我可以在新創建的數據庫中運行上述腳本,但仍然會出現此錯誤。如果索引可能會快速損壞(在空表上創建2個插入),那麼我會擔心SQL Server的穩定性。另外,如上所述,我發現「其他」原因在網上提出這個消息,而且他們實際上並沒有索引損壞。 – 2009-07-03 10:17:50

回答

0

我設法弄清楚是什麼原因導致了這個錯誤,試圖從頭開始構建這個腳本,在我去的時候添加了部分內容。

如果視圖是作爲CREATE SCHEMA語句的一部分創建的,則會產生一些錯誤。如果我將CREATE SCHEMA分成它自己的批處理,然後分別創建表和視圖,則一切正常。


早該編輯 - 我在Connect here上提出這個問題。它被確認爲SQL Server 2008中的一個問題。

內部版本(在2010年)表示它已不再是問題,並且我(僅在2016年)確認該問題中的腳本不會生成在SQL Server 2012中出現同樣的錯誤。該修復沒有被移植到SQL Server 2008。

0

你有索引損壞。運行checkdb並查看它給你的錯誤。你可以做的最簡單的事情就是重建索引。

如果它適用於你的sitution,也可以看看這個KB article

另請注意,將一個主鍵放在GUID列上會在其上創建一個聚集索引,這是您可以執行的最差性能表現。

+0

索引損壞 - 在10分鐘前創建的數據庫/模式/索引中,專門用於此原型? (另外,在新數據庫中可重複使用) 另外,是的,瞭解使用GUID的各種問題。但這就是我在這個數據庫中所堅持的。客戶的實際指導實際上是用newsequentialid()生成的。目前不擔心表現。 – 2009-07-03 09:57:00