SQL SERVER系统存储过程SP_Monitor修改

时间:2022-03-24 10:36:13
大家好:

我现在的数据库是SQL SERVER2008,有个普通用户trtest需要执行系统存储过程SP_Monitor,而SP_Monitor中有限制,

if (not (is_srvrolemember('sysadmin') = 1))  -- Make sure that it is the SA executing this.
        begin
                raiserror(15247,-1,-1)
                return(1)
        end

对于普通用户trtest,我不想赋予sysadmin权限,所以想问:

1、不改系统存储过程,不赋予sysadmin权限情况下,我如何能达到?

2、如何修改系统存储过程?直接修改提示:

消息 208,级别 16,状态 6,过程 sp_monitor,第 173 行
对象名 'sys.sp_monitor' 无效。

谢谢!

9 个解决方案

#1


较有难度的帖子,在微软的论坛也发了!要求必须用这个名称,sp_monitor!

#2


不能修改2008中的系统存储过程。

楼主,你可以换个思路。虽然不能修改系统存储过程,但可以新建一个存储过程,达到同样的目的。步骤如下:
1、先通过语句:sp_helptext 'sp_monitor'  查看该系统存储过程的源代码
2、新建个存储过程,将步骤1的源代码复制过来,将其中的
if (not (is_srvrolemember('sysadmin') = 1)) -- Make sure that it is the SA executing this.
  begin
  raiserror(15247,-1,-1)
  return(1)
  end

这些语句删除。
3、最后将执行新存储过程的权限赋予普通用户trtest即可。

#3


 

create procedure sys.sp_monitor
as
if (not (is_srvrolemember('sysadmin') = 1))  -- 改这里?
        begin
                raiserror(15247,-1,-1)
                return(1)
        end

/*
**  Declare variables to be used to hold current monitor values.
*/
declare @now  datetime
declare @cpu_busy  int
declare @io_busy int
declare @idle int
declare @pack_received int
declare @pack_sent int
declare @pack_errors int
declare @connections int
declare @total_read int
declare @total_write int
declare @total_errors int

declare @oldcpu_busy  int /* used to see if DataServer has been rebooted */
declare @interval int
declare @mspertick int /* milliseconds per tick */

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
set implicit_transactions off
if @@trancount > 0
begin
raiserror(15002,-1,-1,'sp_monitor')
return (1)
end

/*
**  Set @mspertick.  This is just used to make the numbers easier to handle
**  and avoid overflow.
*/
select @mspertick = convert(int, @@timeticks / 1000.0)

/*
**  Get current monitor values.
*/
select
@now = getdate(),
@cpu_busy = @@cpu_busy,
@io_busy = @@io_busy,
@idle = @@idle,
@pack_received = @@pack_received,
@pack_sent = @@pack_sent,
@connections = @@connections,
@pack_errors = @@packet_errors,
@total_read = @@total_read,
@total_write = @@total_write,
@total_errors = @@total_errors

/*
**  Check to see if DataServer has been rebooted.  If it has then the
**  value of @@cpu_busy will be less than the value of spt_monitor.cpu_busy.
**  If it has update spt_monitor.
*/
select @oldcpu_busy = cpu_busy
from master.dbo.spt_monitor
if @oldcpu_busy > @cpu_busy
begin
update master.dbo.spt_monitor
set
lastrun = @now,
cpu_busy = @cpu_busy,
io_busy = @io_busy,
idle = @idle,
pack_received = @pack_received,
pack_sent = @pack_sent,
connections = @connections,
pack_errors = @pack_errors,
total_read = @total_read,
total_write = @total_write,
total_errors = @total_errors
end

/*
**  Now print out old and new monitor values.
*/
set nocount on
select @interval = datediff(ss, lastrun, @now)
from master.dbo.spt_monitor
/* To prevent a divide by zero error when run for the first
** time after boot up
*/
if @interval = 0
select @interval = 1
select last_run = lastrun, current_run = @now, seconds = @interval
from master.dbo.spt_monitor

select
cpu_busy = substring(convert(varchar(11),
convert(int, ((@cpu_busy * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@cpu_busy - cpu_busy)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@cpu_busy - cpu_busy)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25),
io_busy = substring(convert(varchar(11),
convert(int, ((@io_busy * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@io_busy - io_busy)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@io_busy - io_busy)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25),
idle = substring(convert(varchar(11),
        convert(int, ((convert(bigint,@idle) * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@idle - idle)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@idle - idle)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25)
from master.dbo.spt_monitor

select
packets_received = substring(convert(varchar(11), @pack_received) + '(' +
convert(varchar(11), @pack_received - pack_received) + ')', 1, 25),
packets_sent = substring(convert(varchar(11), @pack_sent) + '(' +
convert(varchar(11), @pack_sent - pack_sent) + ')', 1, 25),
packet_errors = substring(convert(varchar(11), @pack_errors) + '(' +
convert(varchar(11), @pack_errors - pack_errors) + ')', 1, 25)
from master.dbo.spt_monitor

select
total_read = substring(convert(varchar(11), @total_read) + '(' +
convert(varchar(11), @total_read - total_read) + ')', 1, 19),
total_write = substring(convert(varchar(11), @total_write) + '(' +
convert(varchar(11), @total_write - total_write) + ')', 1, 19),
total_errors = substring(convert(varchar(11), @total_errors) + '(' +
convert(varchar(11), @total_errors - total_errors) + ')', 1, 19),
connections = substring(convert(varchar(11), @connections) + '(' +
convert(varchar(11), @connections - connections) + ')', 1, 18)
from master.dbo.spt_monitor

/*
**  Now update spt_monitor
*/
update master.dbo.spt_monitor
set
lastrun = @now,
cpu_busy = @cpu_busy,
io_busy = @io_busy,
idle = @idle,
pack_received = @pack_received,
pack_sent = @pack_sent,
connections = @connections,
pack_errors = @pack_errors,
total_read = @total_read,
total_write = @total_write,
total_errors = @total_errors

return (0) -- sp_monitor

#4



ALTER PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'cdc'
AS
SELECT user_name(); -- Shows execution context is set to SqlUser1.
GO
create procedure cdc.sp_monitor
as
select @@SERVERNAME

使用excute as 来提升权限,用不同的架构来封装sp_monitor

#5


Thank you!
主要是,我们的监控上面有调用到这一存储过程,然后搞监控的人不太会调整,所以必须要用这个名字!
就是想不改名字的情况下完成这一的效果!

#6


引用 5 楼 zhazhuzhao 的回复:
Thank you!
主要是,我们的监控上面有调用到这一存储过程,然后搞监控的人不太会调整,所以必须要用这个名字!
就是想不改名字的情况下完成这一的效果!


请参见偶刚写的  怎样修改SQL Server 2005/2008的系统存储过程

PS:微软的论坛中肯定有人知道这个方法,但他们不想说出来...

#7


看到了,厉害啊,谢谢啊!

#1


较有难度的帖子,在微软的论坛也发了!要求必须用这个名称,sp_monitor!

#2


不能修改2008中的系统存储过程。

楼主,你可以换个思路。虽然不能修改系统存储过程,但可以新建一个存储过程,达到同样的目的。步骤如下:
1、先通过语句:sp_helptext 'sp_monitor'  查看该系统存储过程的源代码
2、新建个存储过程,将步骤1的源代码复制过来,将其中的
if (not (is_srvrolemember('sysadmin') = 1)) -- Make sure that it is the SA executing this.
  begin
  raiserror(15247,-1,-1)
  return(1)
  end

这些语句删除。
3、最后将执行新存储过程的权限赋予普通用户trtest即可。

#3


 

create procedure sys.sp_monitor
as
if (not (is_srvrolemember('sysadmin') = 1))  -- 改这里?
        begin
                raiserror(15247,-1,-1)
                return(1)
        end

/*
**  Declare variables to be used to hold current monitor values.
*/
declare @now  datetime
declare @cpu_busy  int
declare @io_busy int
declare @idle int
declare @pack_received int
declare @pack_sent int
declare @pack_errors int
declare @connections int
declare @total_read int
declare @total_write int
declare @total_errors int

declare @oldcpu_busy  int /* used to see if DataServer has been rebooted */
declare @interval int
declare @mspertick int /* milliseconds per tick */

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
set implicit_transactions off
if @@trancount > 0
begin
raiserror(15002,-1,-1,'sp_monitor')
return (1)
end

/*
**  Set @mspertick.  This is just used to make the numbers easier to handle
**  and avoid overflow.
*/
select @mspertick = convert(int, @@timeticks / 1000.0)

/*
**  Get current monitor values.
*/
select
@now = getdate(),
@cpu_busy = @@cpu_busy,
@io_busy = @@io_busy,
@idle = @@idle,
@pack_received = @@pack_received,
@pack_sent = @@pack_sent,
@connections = @@connections,
@pack_errors = @@packet_errors,
@total_read = @@total_read,
@total_write = @@total_write,
@total_errors = @@total_errors

/*
**  Check to see if DataServer has been rebooted.  If it has then the
**  value of @@cpu_busy will be less than the value of spt_monitor.cpu_busy.
**  If it has update spt_monitor.
*/
select @oldcpu_busy = cpu_busy
from master.dbo.spt_monitor
if @oldcpu_busy > @cpu_busy
begin
update master.dbo.spt_monitor
set
lastrun = @now,
cpu_busy = @cpu_busy,
io_busy = @io_busy,
idle = @idle,
pack_received = @pack_received,
pack_sent = @pack_sent,
connections = @connections,
pack_errors = @pack_errors,
total_read = @total_read,
total_write = @total_write,
total_errors = @total_errors
end

/*
**  Now print out old and new monitor values.
*/
set nocount on
select @interval = datediff(ss, lastrun, @now)
from master.dbo.spt_monitor
/* To prevent a divide by zero error when run for the first
** time after boot up
*/
if @interval = 0
select @interval = 1
select last_run = lastrun, current_run = @now, seconds = @interval
from master.dbo.spt_monitor

select
cpu_busy = substring(convert(varchar(11),
convert(int, ((@cpu_busy * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@cpu_busy - cpu_busy)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@cpu_busy - cpu_busy)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25),
io_busy = substring(convert(varchar(11),
convert(int, ((@io_busy * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@io_busy - io_busy)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@io_busy - io_busy)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25),
idle = substring(convert(varchar(11),
        convert(int, ((convert(bigint,@idle) * @mspertick) / 1000)))
+ '('
+ convert(varchar(11), convert(int, (((@idle - idle)
* @mspertick) / 1000)))
+ ')'
+ '-'
+ convert(varchar(11), convert(int, ((((@idle - idle)
* @mspertick) / 1000) * 100) / @interval))
+ '%',
1, 25)
from master.dbo.spt_monitor

select
packets_received = substring(convert(varchar(11), @pack_received) + '(' +
convert(varchar(11), @pack_received - pack_received) + ')', 1, 25),
packets_sent = substring(convert(varchar(11), @pack_sent) + '(' +
convert(varchar(11), @pack_sent - pack_sent) + ')', 1, 25),
packet_errors = substring(convert(varchar(11), @pack_errors) + '(' +
convert(varchar(11), @pack_errors - pack_errors) + ')', 1, 25)
from master.dbo.spt_monitor

select
total_read = substring(convert(varchar(11), @total_read) + '(' +
convert(varchar(11), @total_read - total_read) + ')', 1, 19),
total_write = substring(convert(varchar(11), @total_write) + '(' +
convert(varchar(11), @total_write - total_write) + ')', 1, 19),
total_errors = substring(convert(varchar(11), @total_errors) + '(' +
convert(varchar(11), @total_errors - total_errors) + ')', 1, 19),
connections = substring(convert(varchar(11), @connections) + '(' +
convert(varchar(11), @connections - connections) + ')', 1, 18)
from master.dbo.spt_monitor

/*
**  Now update spt_monitor
*/
update master.dbo.spt_monitor
set
lastrun = @now,
cpu_busy = @cpu_busy,
io_busy = @io_busy,
idle = @idle,
pack_received = @pack_received,
pack_sent = @pack_sent,
connections = @connections,
pack_errors = @pack_errors,
total_read = @total_read,
total_write = @total_write,
total_errors = @total_errors

return (0) -- sp_monitor

#4



ALTER PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'cdc'
AS
SELECT user_name(); -- Shows execution context is set to SqlUser1.
GO
create procedure cdc.sp_monitor
as
select @@SERVERNAME

使用excute as 来提升权限,用不同的架构来封装sp_monitor

#5


Thank you!
主要是,我们的监控上面有调用到这一存储过程,然后搞监控的人不太会调整,所以必须要用这个名字!
就是想不改名字的情况下完成这一的效果!

#6


引用 5 楼 zhazhuzhao 的回复:
Thank you!
主要是,我们的监控上面有调用到这一存储过程,然后搞监控的人不太会调整,所以必须要用这个名字!
就是想不改名字的情况下完成这一的效果!


请参见偶刚写的  怎样修改SQL Server 2005/2008的系统存储过程

PS:微软的论坛中肯定有人知道这个方法,但他们不想说出来...

#7


看到了,厉害啊,谢谢啊!