我只是原型化一个新系统,用于推迟某些操作,直到某个数据库超时。我想出了(我认为)一个非常简单的模式。我第一次在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选项看起来都适合使用索引视图,如果它们不是,我希望抛出一个不太暴力的错误。
任何想法?
正如我在对Mladen Prajdic的评论中指出的 - 我可以在新创建的数据库中运行上述脚本,但仍然会出现此错误。如果索引可能会快速损坏(在空表上创建2个插入),那么我会担心SQL Server的稳定性。另外,如上所述,我发现“其他”原因在网上提出这个消息,而且他们实际上并没有索引损坏。 – 2009-07-03 10:17:50