
CS模式下,数据是放在客户本地的服务器上。而大部分客户并没有专业能力去维护他们的SQL Server,老版本数据库系统设置更是较旧。因此,总是遇到客户反馈的损坏问题。客户 alter 或 drop 某个存储过程、或者打开存储过程列表时,执行中止并提示“架构损坏”。
-- checkdb 中断报错DBCC CHECKDB(DBName)-- 类似的,修复也报错DBCC CHECKDB (dbname, REPAIR_ALLOW_DATA_LOSS);
CHECKDB 在数据库 'dbname' 中发现 0 个分配错误和 0 个一致性错误。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
消息 211,级别 23,状态 16,第 1 行
可能发生了架构损坏。请运行 DBCC CHECKCATALOG。
除了这些错误信息,完全不知道哪些表有问题。又对这个库的所有表都 checktable ,也无报错。可以确认,当前的表结构及数据是没问题的,断定是当前数据库的系统表出现了问题。
好吧,打开 Profiler 跟着(RPC:Startding、RPC:Completed、SP:Startding、SP:Completed、SP:StmtStartding、SP:StmtCompleted、SQL:…),甚至还跟踪了锁的请求及释放(有点多余了)。然后删除某报错的存储过程,跟踪到以下SQL:

图一
把以上跟踪出现的涉及表查询一遍:
select * from sys.all_objectsselect * from sys.database_principalsselect * from sys.sql_modulesselect * from sys.system_sql_modules
发现是系统视图 sys.sql_modules 报错!该视图返回函数、视图、存储过程的定义。查看该视图的定义:
sp_helptext 'sys.sql_modules'--定义CREATE VIEW sys.sql_modules ASSELECT object_id = o.id,definition = object_definition(o.id),uses_ansi_nulls = sysconv(bit, o.status & 0x40000), -- OBJMOD_ANSINULLSuses_quoted_identifier = sysconv(bit, o.status & 0x80000), -- OBJMOD_QUOTEDIDENTis_schema_bound = sysconv(bit, o.status & 0x20000), -- OBJMOD_SCHEMABOUNDuses_database_collation = sysconv(bit, o.status & 0x100000), -- OBJMOD_USESDBCOLLis_recompiled = sysconv(bit, o.status & 0x400000), -- OBJMOD_NOCACHEnull_on_null_input = sysconv(bit, o.status & 0x200000), -- OBJMOD_NULLONNULLexecute_as_principal_id = x.indepidFROM sys.sysschobjs oLEFT JOIN sys.syssingleobjrefs x ON x.depid = o.id AND x.class = 22 AND x.depsubid = 0 -- SRC_OBJEXECASOWNERWHERE o.pclass <> 100 -- x_eunc_ServerAND ((o.type = 'TR' AND has_access('TR', o.id, o.pid, o.nsclass) = 1)OR (type IN ('P','V','FN','IF','TF','RF','IS') AND has_access('CO', o.id) = 1)OR (type IN ('R','D') AND o.pid = 0))

图二
直接点击一个查询窗口,以DAC管理员访问:admin:<instancename>

图三
好了,进入损坏的数据库,查询系统视图:
select * from sys.sysschobjsselect * from sys.syssingleobjrefs
SELECT object_id = o.id,definition = object_definition(o.id)FROM sys.sysschobjs oLEFT JOIN sys.syssingleobjrefs x ON x.depid = o.id AND x.class = 22 AND x.depsubid = 0
select object_definition(id),id from sys.sysschobjs where name='usp_mytest'
果然是报错的就是它,错误就是最开始的信息。但是,不确定是否其他对象也可能出错,所以执行以下SQL,把所有输出都执行一遍。
select concat('selelct object_definition(',id,')') from sys.sysschobjs
select id,name,type,concat('select * from sys.',name) from sys.sysschobjs WHERE NAME LIKE 'sys%' order by type,NAME
以下几张表要删除的:
select id from sys.sysschobjs where name='usp_mytest'delete from sys.sysschobjs where id=xxxxxxxxxxxdelete from sys.syscolpars where id=xxxxxxxxxxxdelete from sys.syssoftobjrefs where depid=xxxxxxxxxxx
-- 可创建原来的存储过程-- Create procedure usp_mytestALTER DATABASE dbname SET EMERGENCY;GOALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;GODBCC CHECKDB (dbname) WITH TABLOCKGOALTER DATABASE dbname SET MULTI_USER;GOALTER DATABASE dbname SET ONLINE;GO
文章转载自SQLServer,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




