错误描述:
最近一段时间早上查看我维护的一个网站,每次都出现连接数据库超时一过期的提示。在服务器上登陆不了sqlserver。在服务中也停止不了sqlserver服务。
只能在任务管理器中强制结束进程,然后才能重启sqlserver服务。
由于在0点以后服务器有任务计划执行。每天数据库也会执行备份计划。还有asp.net存在两个定时任务。怀疑是这里的问题。可是在几天处理的过程中,停止计划任务。调整定时任务执行的时间问题依旧。只是在事件查看器中确定数据库不能访问的时间是早上3点以后。
怀疑有阻塞。但是阻塞没法查看,因为出现问题后数据库登陆不了。重启后又没问题了。怎么办?这时想到了专用管理员链接(DAC)。在一天的早上又出现问题后用DAC登陆上了sqlserver.
在master数据库执行查阻塞语句:
select * from sysprocesses where dbid in (select dbid from sysdatabases where name='数据库名') and blocked>0
很是惊讶,没发现阻塞。
然后执行语句查看正在运行的sql线程:
select * from sys.dm_exec_requests er cross apply sys.dm_exec_sql_text(er.sql_handle) where database_id=7
发现session_id=108的线程状态一直是running.而且从3点多都开始运行到现在。其他的线程都是挂起状态
--根据session_id查看这个一直在运行的语句
dbcc inputbuffer(108)
执行结果为:
update xm set isupdate=0 where xm_id=153442
然后单独在查询分析器中执行此语句,结果一直在运行,但是一直不成功,在查询分析器中按取消,取消不了。
利用kill 108 杀进程,但是杀不掉。重启不了数据库,只能在任务管理器中强制结束进程,然后才能重启sqlserver。
这现在可以确定罪魁祸首就是此语句
我对选择了其他两张表做更新测试,没有问题。现在基本确定是此表由于某种原因损坏了。需要修复此表。
如何修复呢?
在服务器上打开sql数据库。然后打开一个查询分析器窗口
首先执行重启服务器操作。然后执行以下语句:
use master
--修复表
declare @dbname varchar(255)
set @dbname='数据库名'
exec sp_dboption @dbname,'single user','true'
执行上面的语句目的是为了以独占的方式打开数据库。因为相应的数据库表修复语句需要在独占方式执行。在这个执行过程中如果出现提示sp_dboption不能执行,有其他用户在使用数据库之类的提示,则要再重启数据库,快速操作上面的语句。执行成功后运行如下两条语句:
dbcc checktable('数据库名.dbo.xm',REPAIR_ALLOW_DATA_LOSS)
dbcc checktable('数据库名.dbo.xm',REPAIR_REBUILD)
这两条语句会对数据库www_rztong_com_cn中的xm表进行修复操作。如果某行语句不能修复,则会自动删除该行。执行成功后要执行如下语句取消数据库的独占状态。
exec sp_dboption @dbname,'single user','false'
执行后对此数据库执行更新测试,看问题是否解决:
select top 10 * from 数据库名.dbo.xm
UPDATE 数据库名.dbo.xm SET IsUpdate=0,xm_name='门窗的革命成功商人的机遇宏一佳智能门窗' WHERE xm_id=1
结果执行没问题。问题解决。
如果需要对整个数据库进行修复。而不是修复单独的一张表,则可以执行如下语句:
dbcc checkdb(@databasename,REPAIR_ALLOW_DATA_LOSS)
dbcc checkdb(@databasename,REPAIR_REBUILD)