设为首页 收藏本站
查看: 1101|回复: 0

[经验分享] 通过本地Agent监控Azure sql database

[复制链接]

尚未签到

发表于 2017-6-30 06:16:25 | 显示全部楼层 |阅读模式
背景:
  虽然Azure sql database有DMVs可以查看DTU等使用情况,但记录有时间限制,不会一直保留。为了更好监控Azure_sql_database上各个库的DTU使用情况、数据库磁盘使用情况、阻塞等情况。通过本地的Agent的job使用link server 链接到各个Azure sql database 对应库(本地Ip能直连azure sql database),把相关的信息读取出来,存储在本地已新建好的对应表中,通过分析本地对应表中记录来实现监控azure sql database各个库的情况。如需了解azure sql database 与 ssms在开发上的一些区别。

基本思路:
  第一步:本地库中新建好相应的表用来存放从azure sql database 上读取的记录;
  第二步:在本地实例中新建好各个对应azure sql database 各个库的数据库链接,并把相关信息存放在azure_dblink_configure表中;
  第三步:在本地库中新建好存储过程用来处理azure sql database上的记录存储在本地对应的表中;
  第四步:在本地数据库的代理中新建job通过计划循环调用存储过程;

本地测试环境:
  Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
  Feb 10 2012 19:39:15
  Copyright (c) Microsoft Corporation
  Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )

具体实现步骤:

第一步:新建库新建表








DSC0000.gif DSC0001.gif



IF DB_ID('azure_monitor') IS NOT NULL
     DROP DATABASE azure_monitor;
GO
CREATE DATABASE azure_monitor;
GO
USE azure_monitor;
GO
IF OBJECT_ID('azure_dblink_configure','U') IS NOT NULL
DROP TABLE azure_dblink_configure;
  
CREATE TABLE azure_dblink_configure
     (
       id INT IDENTITY(1, 1) ,
       dblink NVARCHAR(200) NOT NULL ,
       dbname NVARCHAR(50) NOT NULL ,
       descriptions NVARCHAR(200) ,  
       okflag BIT DEFAULT ( 1 )
                  NOT NULL ,   
       createuser NVARCHAR(20) ,  
       createdate DATETIME DEFAULT ( GETDATE() )
                           NOT NULL ,  
       updatedate DATETIME DEFAULT ( GETDATE() )
                           NOT NULL   
     );
ALTER TABLE azure_dblink_configure ADD CONSTRAINT PK_azure_dblink_configure PRIMARY KEY(dblink,dbname);

IF OBJECT_ID('monitor_azure_spaceused','U') IS NOT NULL
DROP TABLE monitor_azure_spaceused;
  
CREATE TABLE monitor_azure_spaceused
     (
       id INT IDENTITY(1, 1)
              PRIMARY KEY ,
       dblink NVARCHAR(200),
       database_name VARCHAR(200) ,
       [sum_database(G)] decimal(18, 2),
       execute_time_beijing DATETIME,
       create_time DATETIME DEFAULT(GETDATE())
     );

IF OBJECT_ID('monitor_azure_DTU', 'U') IS NOT NULL
     DROP TABLE monitor_azure_DTU;
  
CREATE TABLE monitor_azure_DTU
     (
       id INT IDENTITY(1, 1)
              PRIMARY KEY ,
       dblink NVARCHAR(200),
       database_name VARCHAR(200) ,
       beijin_end_time DATETIME NULL ,
       avg_cpu_percent DECIMAL NULL ,
       avg_data_io_percent DECIMAL NULL ,
       avg_log_write_percent DECIMAL NULL ,
       avg_memory_usage_percent DECIMAL NULL ,
       xtp_storage_percent DECIMAL NULL ,
       max_worker_percent DECIMAL NULL ,
       max_session_percent DECIMAL NULL ,
       dtu_limit INT NULL ,
       create_time DATETIME DEFAULT ( GETDATE() )
);
  
CREATE INDEX IX_monitor_azure_DTU ON monitor_azure_DTU ([database_name]) INCLUDE ([beijin_end_time]);
  
IF OBJECT_ID('monitor_azure_blocked', 'U') IS NOT NULL
     DROP TABLE monitor_azure_blocked;
  
CREATE TABLE monitor_azure_blocked
     (
       id INT IDENTITY(1, 1)
              PRIMARY KEY ,
       dblink NVARCHAR(200),
       dbname VARCHAR(200) ,
       spid SMALLINT NOT NULL ,
       kpid SMALLINT NOT NULL ,
       blocked SMALLINT NOT NULL ,
       waittype [VARCHAR](MAX) NOT NULL ,
       waittime BIGINT NOT NULL ,
       lastwaittype NCHAR(32) NOT NULL ,
       waitresource NCHAR(256) NOT NULL ,
       dbid SMALLINT NOT NULL ,
       uid SMALLINT NULL ,
       cpu INT NOT NULL ,
       physical_io BIGINT NOT NULL ,
       memusage INT NOT NULL ,
       login_time DATETIME NOT NULL ,
       last_batch DATETIME NOT NULL ,
       ecid SMALLINT NOT NULL ,
       open_tran SMALLINT NOT NULL ,
       status NCHAR(30) NOT NULL ,
       sid [VARCHAR](MAX) NOT NULL ,
       hostname NCHAR(128) NOT NULL ,
       program_name NCHAR(128) NOT NULL ,
       hostprocess NCHAR(10) NOT NULL ,
       cmd NCHAR(16) NOT NULL ,
       nt_domain NCHAR(128) NOT NULL ,
       nt_username NCHAR(128) NOT NULL ,
       net_address NCHAR(12) NOT NULL ,
       net_library NCHAR(12) NOT NULL ,
       loginame NCHAR(128) NOT NULL ,
       context_info [VARCHAR](MAX) NOT NULL ,
       sql_handle [VARCHAR](MAX) NOT NULL ,
       stmt_start INT NOT NULL ,
       stmt_end INT NOT NULL ,
       request_id INT NOT NULL ,
       [text]  NVARCHAR(max),
       createtime DATETIME DEFAULT ( GETDATE() )
     );
View Code
第二步:新建link server,针对Azure sql database各个库新建链接






EXEC sp_addlinkedserver
@server='azure_sql_db_01',
@srvproduct='',      
@provider='sqlncli',
@datasrc='XXXXXX.database.chinacloudapi.cn',
@location='',
@provstr='',
@catalog='your_DB_name'        
EXEC sp_addlinkedsrvlogin 'azure_sql_db_01', 'false', NULL, '用户名', '用户密码';

EXEC sp_serveroption 'azure_sql_db_01', 'rpc out', true;


IF NOT EXISTS ( SELECT  *
                 FROM    azure_dblink_configure
                 WHERE   dblink = N'azure_sql_db_01'
                         AND dbname = N'your_DB_name' )
     BEGIN
         INSERT  INTO azure_dblink_configure
                 ( dblink ,
                   dbname ,
                   descriptions ,
                   createuser
                 )
         VALUES  ( N'azure_sql_db_01' ,
                   N'your_DB_name' ,
                   N'某某项目' ,
                   N'新建人员'
                 );
     END;
View Code
第三步:在本地新建存储过程








CREATE  PROCEDURE dbo.Azure_p_monitor
AS
     BEGIN
         SET NOCOUNT ON;
         DECLARE @linkserver NVARCHAR(MAX);
         DECLARE @dblink NVARCHAR(200);   
         DECLARE @dbname NVARCHAR(50);     
         DECLARE @id INT;                  
         DECLARE cur_wen CURSOR FORWARD_ONLY
         FOR
             SELECT  id ,
                     dblink ,
                     dbname
             FROM    azure_dblink_configure
             WHERE   okflag = 1
             ORDER BY id ASC;
         OPEN cur_wen;
         FETCH NEXT FROM cur_wen INTO @id, @dblink, @dbname;
         WHILE ( @@FETCH_STATUS = 0 )
             BEGIN
                 SELECT  @linkserver = '[' + @dblink + ']' + '.' + '['
                         + @dbname + ']';
               
                 BEGIN TRY
                     
                     BEGIN
                         DECLARE @addtime DATETIME;
                     
                         IF EXISTS ( SELECT  1
                                     FROM    monitor_azure_DTU
                                     WHERE   database_name = @dbname )
                             BEGIN
                                 SELECT  @addtime = MAX([beijin_end_time])
                                 FROM    monitor_azure_DTU
                                 WHERE   database_name = @dbname;
                             END;
                         ELSE   
                             SELECT  @addtime = DATEADD(dd, -1, GETDATE());
                        
                         DECLARE @addtime_nvar NVARCHAR(200);
                         SELECT  @addtime_nvar = CAST(@addtime AS NVARCHAR(200));
                         EXEC ( '  INSERT  INTO monitor_azure_DTU
                         ( dblink,
                         database_name ,
                         beijin_end_time ,
                         avg_cpu_percent ,
                         avg_data_io_percent ,
                         avg_log_write_percent ,
                         avg_memory_usage_percent ,
                         xtp_storage_percent ,
                         max_worker_percent ,
                         max_session_percent ,
                         dtu_limit
                         )
                         SELECT '+''''+@dblink+''''+ ' as dblink,'+'''' + @dbname + ''''+' AS database_name ,
                         DATEADD(hh, 8, a.end_time) as beijin_end_time ,
                         a.avg_cpu_percent ,
                         a.avg_data_io_percent ,
                         a.avg_log_write_percent ,
                         a.avg_memory_usage_percent ,
                         a.xtp_storage_percent ,
                         a.max_worker_percent ,
                         a.max_session_percent ,
                         a.dtu_limit
                         FROM  ' + @linkserver + '.sys.dm_db_resource_stats as a
                         WHERE   end_time > DATEADD(hh, -8,'+'''' +@addtime_nvar +'''' + ')');
                     END;
                     
                     BEGIN
                         DECLARE @spid NVARCHAR(50);
                         SELECT  @spid = CAST(@@spid AS NVARCHAR(50));
                        
                         EXEC ('
                         INSERT INTO monitor_azure_blocked( dblink,dbname, spid, kpid, blocked, waittype, waittime, lastwaittype, waitresource, [dbid], [uid], cpu, physical_io, memusage, login_time, last_batch, ecid, open_tran, [status], [sid], hostname, [program_name], hostprocess, cmd, nt_domain, nt_username, net_address, net_library, loginame, [context_info], [sql_handle], stmt_start, stmt_end, request_id,text)
                         SELECT '+''''+@dblink+''''+' as dblink,*
                         FROM  openquery('+@dblink+','' SELECT  b.name AS dbname ,
                         a.spid ,
                         a.kpid ,
                         a.blocked ,
                         a.waittype ,
                         a.waittime ,
                         a.lastwaittype ,
                         a.waitresource ,
                         a.[dbid] ,
                         a.[uid] ,
                         a.cpu ,
                         a.physical_io ,
                         a.memusage ,
                         DATEADD(hh, 8, a.login_time) AS login_time ,--已换算成北京时间
                         DATEADD(hh, 8, a.last_batch) AS last_batch ,--已换算成北京时间
                         a.ecid ,
                         a.open_tran ,
                         a.[status] ,
                         a.[sid] ,
                         a.hostname ,
                         a.[program_name] ,
                         a.hostprocess ,
                         a.cmd ,
                         a.nt_domain ,
                         a.nt_username ,
                         a.net_address ,
                         a.net_library ,
                         DATEADD(hh, 8, a.login_time) AS loginame ,--换算成北京时间
                         a.[context_info] ,
                         a.[sql_handle] ,
                         a.stmt_start ,
                         a.stmt_end ,
                         a.request_id,
                         c.text from sys.sysprocesses a inner join sys.databases b ON a.[dbid]=b.database_id  cross apply sys.dm_exec_sql_text(a.sql_handle) c
                         WHERE   a.spid > 50
                         AND a.blocked > 0
                         AND a.spid <>'+@SPID+''')' );
                       
                     END;
                     
                     BEGIN
                         EXEC
                         ( 'INSERT  INTO [dbo].[monitor_azure_spaceused]
                         ( dblink,
                         database_name ,
                         [sum_database(G)] ,
                         execute_time_beijing
                         )
                         SELECT '+''''+@dblink+ ''''+' as dblink,'+''''+ @dbname+ ''''+' AS database_name , --监控的具体库名
                         ROUND(( SUM(reserved_page_count) * 8.0 / 1024 ) / 1024, 2) AS [sum_database(G)] ,
                         DATEADD(hh, 8, GETDATE()) AS execute_time_beijing
                         FROM  '+  @linkserver+'.sys.dm_db_partition_stats' );
                     END;
              
                 END TRY
            
                 BEGIN CATCH
                     SELECT  ERROR_MESSAGE();
                     
                     
                     
                 END CATCH;
            
                 FETCH NEXT FROM cur_wen INTO @id, @dblink, @dbname;
             END;
        
         DEALLOCATE cur_wen;
         SET NOCOUNT OFF;
     END;
View Code  
第四步:本地Agent 使用job调用存储过程

Agent中job设置详情省略,可以参考数据库出现阻塞及时邮件预警提醒(下)。注意计划时间间隔合理设置。



参考资料:




sys.dm_db_resource_stats
sys.resource_stats
补充:


1)可以考虑用SSIS来实现监控;

2)也可以考虑不新建DBLink,直接在agent中使用sqlcmd来调用azure sql database。

3)为了便于直观查看监控的数据,可以考虑用Power BI等把监控的数据友好展示出来。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-389507-1-1.html 上篇帖子: 认识 Azure 下篇帖子: Azure IoT 技术研究系列1-入门篇
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表