前几天在论坛上发了一个帖子”SQL Server 2008如何查看表结构修改记录“,很感谢马上有人热心回复并给出建议,现在我把问题的原因和到最后的解决办法与大家分享,希望对大家有帮助.
问题:上午一上班就有用户打电话说系统出了问题,第一反应是马上去看系统是否有BUG,经过测试之后发现系统是完全没有问题的,但是原来能使用此页面的用户竟然都没有了权限,再次DEBUG系统时,发现从数据库的权限表里拿到的数据都是乱码,推测应该是有人修改了表的”排序规则”,使得中文部分都变成了问号,最郁闷的是查看日志之后也不知道是谁修改的,赶紧先把数据库恢复,之后分析原因主要有以下几点:
1.对数据库权限粒度划分不明确;
2.对数据库修改的日志没有记录;
解决办法:
1.创建数据库修改日志表(如何害怕不小心被删除,可以参考防止表被删除的触发器)
- USE [QSBN]
 - GO
 - SET ANSI_NULLS ON
 - GO
 - SET QUOTED_IDENTIFIER ON
 - GO
 - — 创建数据库修改日志表
 - CREATE TABLE dbo.[DatabaseModifiedLog](
 - [ID] INT IDENTITY(1,1) NOT NULL,
 - [EventType] NVARCHAR(500) NULL,
 - [PostTime] DATETIME NULL,
 - [ClientUser] NVARCHAR(10) NULL,
 - [ServerName] NVARCHAR(250) NULL,
 - [LoginName] NVARCHAR(250) NULL,
 - [UserName] NVARCHAR(250) NULL,
 - [DatabaseName] NVARCHAR(250) NULL,
 - [SchemaName] NVARCHAR(250) NULL,
 - [ObjectName] NVARCHAR(250) NULL,
 - [ObjectType] NVARCHAR(250) NULL,
 - [CommandText] NVARCHAR(MAX) NULL,
 - [EventData] XML NULL,
 - PRIMARY KEY CLUSTERED
 - ([ID] ASC)
 - WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 - )ON [PRIMARY]
 - GO
 
2.创建数据库级别的触发器
- — 创建数据库级别的触发器
 - CREATE TRIGGER [DataBase_DDL_TRIGGER]
 - ON DATABASE
 - FOR DDL_DATABASE_LEVEL_EVENTS
 - AS
 - DECLARE @EventData XML
 - DECLARE @EventType NVARCHAR(250)
 - DECLARE @PostTime DATETIME
 - DECLARE @SPID NVARCHAR(6)
 - DECLARE @ClientUser NVARCHAR(50)
 - DECLARE @ServerName NVARCHAR(250)
 - DECLARE @LoginName NVARCHAR(250)
 - DECLARE @UserName NVARCHAR(250)
 - DECLARE @DatabaseName NVARCHAR(250)
 - DECLARE @SchemaName NVARCHAR(250)
 - DECLARE @ObjectName NVARCHAR(250)
 - DECLARE @ObjectType NVARCHAR(250)
 - DECLARE @CommandText NVARCHAR(MAX)
 - SET @EventData = EVENTDATA();
 - SET @EventType = @EventData.value(‘(/EVENT_INSTANCE[1]/EventType[1])’, ‘NVARCHAR(250)’)
 - SET @PostTime = @EventData.value(‘(/EVENT_INSTANCE[1]/PostTime[1])’, ‘DATETIME’)
 - SET @SPID = @EventData.value(‘(/EVENT_INSTANCE[1]/SPID[1])’, ‘NVARCHAR(6)’)
 - SELECT @ClientUser = hostname FROM master..sysprocesses WHERE spid = @SPID
 - SET @ServerName = @EventData.value(‘(/EVENT_INSTANCE[1]/ServerName[1])’, ‘NVARCHAR(250)’)
 - SET @LoginName = @EventData.value(‘(/EVENT_INSTANCE[1]/LoginName[1])’, ‘NVARCHAR(250)’)
 - SET @UserName = @EventData.value(‘(/EVENT_INSTANCE[1]/UserName[1])’, ‘NVARCHAR(250)’)
 - SET @DatabaseName = @EventData.value(‘(/EVENT_INSTANCE[1]/DatabaseName[1])’, ‘NVARCHAR(250)’)
 - SET @SchemaName = @EventData.value(‘(/EVENT_INSTANCE[1]/SchemaName[1])’, ‘NVARCHAR(250)’)
 - SET @ObjectName = @EventData.value(‘(/EVENT_INSTANCE[1]/ObjectName[1])’, ‘NVARCHAR(250)’)
 - SET @ObjectType = @EventData.value(‘(/EVENT_INSTANCE[1]/ObjectType[1])’, ‘NVARCHAR(250)’)
 - SET @CommandText = @EventData.value(‘(/EVENT_INSTANCE[1]/TSQLCommand[1]/CommandText[1])’, ‘NVARCHAR(MAX)’)
 - — 将记录插入到数据库
 - INSERT INTO [dbo].[DatabaseModifiedLog]
 - ([EventType]
 - ,[PostTime]
 - ,[ClientUser]
 - ,[ServerName]
 - ,[LoginName]
 - ,[UserName]
 - ,[DatabaseName]
 - ,[SchemaName]
 - ,[ObjectName]
 - ,[ObjectType]
 - ,[CommandText]
 - ,[EventData])
 - VALUES
 - (@EventType
 - ,@PostTime
 - ,@ClientUser
 - ,@ServerName
 - ,@LoginName
 - ,@UserName
 - ,@DatabaseName
 - ,@SchemaName
 - ,@ObjectName
 - ,@ObjectType
 - ,@CommandText
 - ,@EventData)
 - GO
 - SET ANSI_NULLS OFF
 - GO
 - SET QUOTED_IDENTIFIER OFF
 - GO
 - DISABLE TRIGGER [DataBase_DDL_TRIGGER] ON DATABASE
 - GO
 - ENABLE TRIGGER [DataBase_DDL_TRIGGER] ON DATABASE
 - GO
 
3.执行DDL语句之后,查看日志表中数据,如图:
