今天接到客户电话,说操作数据无法保存。经过分析,发现他的数据库已经有5G多的大小,而最终发现有张表的索引出错了,用DBCC CHECK也无力回天。
每次用select * from ln003082 语句查询,都报如下错误:
服务器: 消息 605,级别 21,状态 1,行 1 试图从数据库 'ln_fl0125' 中提取的逻辑页 (1:629904) 属于对象 '869578136',而非对象 'LN003082'。
连接中断
没办法,只能想办法恢复了。还好有几位老手在身边。于是通如以下步骤勉强恢复有效数据,当然,有部份单子数据是丢失了。只能叫客户再去补了。
首先要确定哪些数据回不来了,通过游标来一一确定哪些数据无效了。
declare @bill_no varchar(20) declare @shop_no varchar(20) DECLARE @QTY INT
DECLARE terminal_changecursor CURSOR FOR select bill_no,shop_no from terminal_change group by shop_no,bill_no ORDER by shop_no,bill_no
OPEN terminal_changecursor FETCH NEXT FROM terminal_changecursor into @bill_no ,@shop_no WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM terminal_changecursor into @bill_no ,@shop_no
PRINT @bill_no +'-'+@shop_no IF NOT ( (@bill_no='MB10010033' AND @shop_no = 'P9ZT') OR (@bill_no='MT90910001' AND @shop_no = 'P9ZT') OR (@bill_no='MT00110002' AND @shop_no = 'P10D') OR (@bill_no='MB10010034' AND @shop_no = 'P9ZT') OR (@bill_no='MB10010035' AND @shop_no = 'P9ZT')
) select @QTY=sum(bill_qty) from LN003082 WHERE bill_no=@bill_no AND shop_no=@shop_no ENDEND
DEALLOCATE terminal_changecursor GO
通过上面的语句,可以查到哪些单号的数据出了问题。用IF跳过有问题的数据,当select sum通过游标查询时,如果有问题的数据,就会停下来中断,根据print出来的单号,将其加入下次IF中,这个步骤很枯燥。不过一般不会出现过多丢失的数据,也只能这样一一确定了。
接下来就是根据查询出来有问题的数据,进行过滤恢复了。
恢复方法脚本如下:
主要有3步。
--说明:终端变动数据表坏了,丢失五张数据,请通知重传
--1。重建表LN003082为LN003082_new,用于转移有效数据 select * into LN003082_new from LN003082 where 1=2 GO
CREATE INDEX [IX_TERMINAL_CHANGE_BILL_NO] ON [dbo].[LN003082_new]([BILL_NO], [SHOP_NO]) ON [PRIMARY] GO
CREATE INDEX [R_TC_GOODS_FK] ON [dbo].[LN003082_new]([GOODS_NO]) ON [PRIMARY] GO
CREATE INDEX [R_TC_SHOP_FK] ON [dbo].[LN003082_new]([SHOP_NO]) ON [PRIMARY] GO
CREATE INDEX [IX_TERMINAL_CHANGE_VALID_DATE] ON [dbo].[LN003082_new]([VALID_DATE]) ON [PRIMARY] GO
CREATE INDEX [IX_TERMINAL_CHANGE] ON [dbo].[LN003082_new]([ACC_VALID_DATE]) ON [PRIMARY] GO
CREATE INDEX [IX_TERMINAL_CHANGE_INTER_BILLNO] ON [dbo].[LN003082_new]([INTER_BILLNO], [SHOP_NO]) ON [PRIMARY] GO
--2。将有效数据导入LN003082_new
declare @bill_no varchar(20) declare @shop_no varchar(20) DECLARE @QTY INT
DECLARE terminal_changecursor CURSOR FOR select bill_no,shop_no from terminal_change group by shop_no,bill_no ORDER by shop_no,bill_no
OPEN terminal_changecursor FETCH NEXT FROM terminal_changecursor into @bill_no ,@shop_no WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM terminal_changecursor into @bill_no ,@shop_no
IF NOT ( (@bill_no='MB10010033' AND @shop_no = 'P9ZT') OR (@bill_no='MT90910001' AND @shop_no = 'P9ZT') OR (@bill_no='MT00110002' AND @shop_no = 'P10D') OR (@bill_no='MB10010034' AND @shop_no = 'P9ZT') OR (@bill_no='MB10010035' AND @shop_no = 'P9ZT') ) INSERT INTO LN003082_new SELECT * FROM LN003082 WHERE bill_no=@bill_no AND shop_no=@shop_no END
DEALLOCATE terminal_changecursor GO
--3。将转移好数据的表改名为LN003082 exec sp_rename 'LN003082','LN003082olderror' exec sp_rename 'LN003082_new','LN003082'
=================================================== |