分享一个前两天写的自动监控blocking 的脚本(基于12C)
闲话不说直接上脚本。
用于再rac环境下监控本机所有非standby db的blocking 情况。11g应该也适用。
blocking2.sql
set serveroutput on
set lines 300
declare
v_msg varchar2(20000);
v_title varchar2(20000);
v_find_obj_sql varchar2(20000);
v_full_sql_txt varchar2(20000);
v_objname varchar2(30) ;
function send_mail(vc_subject in varchar2,vc_message in varchar2)return pls_integer
asmail_sendr constant varchar(32) := 'db@dex.com';mail_recpt constant varchar(32) := 'db@dex.com';
BEGINUTL_MAIL.send(sender => mail_sendr,recipients => mail_recpt,subject => vc_subject,message => vc_message,mime_type => 'text; charset=us-ascii');return 1;
exception when others thenreturn 0;
END;
function get_full_sqltext(vc_sqlid in varchar2) return varchar2
asv_find_sql_txt varchar2(20000) ;v_sql_txt varchar2(20000) ;
beginv_find_sql_txt := 'select max(dbms_lob.substr(sql_fulltext)) FULL_TEXT from v$sql where sql_id=:sqlid ';execute immediate v_find_sql_txt into v_sql_txt using vc_sqlid;return v_sql_txt ;
end;begin
v_find_obj_sql := 'select max(o.owner) || ''.'' ||max(o.object_name) || nvl2 (max(subobject_name), ''.'' || max(subobject_name), null) obj_name from containers(dba_objects) o where o.object_id=:objid and o.con_id=:conid' ;
for rec in (select'Container '||p.name||' Session '||a.sid||' is blokcing session '||b.sid||' duration: '|| lpad (to_char (trunc (w.ctime / 3600)), 3, '0') || ':' ||lpad (to_char (mod (trunc (w.ctime / 60), 60)), 2, '0') || ':' ||lpad (to_char (mod (w.ctime, 60)), 2, '0')||' Lock type ' ||h.type summary,
'Blocker SID :' || a.sid ||chr(10)||
'Blocker Username :' || a.username ||chr(10)||
'Blocker App Machine :' || a.machine ||chr(10)||
'Blocker Serial number :' || a.serial# ||chr(10)||
'Blocker Current Status :' || a.status ||chr(10)||
'Blocker SQL ID current :' || a.sql_id ||chr(10)||
'Blocker Previous SQL ID :' || a.prev_sql_id ||chr(10)||
'Blocker KCML Partition No :' || a.module ||chr(10)||
'Blocker Program name :' || a.program ||chr(10)||
'Blocker Client Information :' || a.client_info ||chr(10)||
'Blocker Application UUID :' || a.ecid ||chr(10)||
'Waiter SID :' || b.sid||chr(10)||
'Waiter Username :' || b.username ||chr(10)||
'Waiter App Machine :' || b.machine ||chr(10)||
'Waiter Serial number :' || b.serial# ||chr(10)||
'Waiter Current Status :' || b.status ||chr(10)||
'Waiter SQL ID current :' || b.sql_id ||chr(10)||
'Waiter Previous SQL ID :' || b.prev_sql_id ||chr(10)||
'Waiter KCML Partition No :' || b.module ||chr(10)||
'Waiter Program name :' || b.program ||chr(10)||
'Waiter Client Information :' || b.client_info ||chr(10)||
'Waiter Application UUID :' || b.ecid details,a.sql_id b_sql_id,a.prev_sql_id b_prev_sql_id,b.sql_id w_sql_id,b.prev_sql_id w_prev_sql_id,p.name pdbname,p.con_id,decode (w.type, 'TX', b.row_wait_obj#,'TM', w.id1) obj_idfrom v$lock h, v$lock w, v$session b, v$session a , v$pdbs pwhere h.block != 0and h.lmode != 0and h.lmode != 1and w.request != 0and w.id1 = h.id1and w.id2 = h.id2and h.sid = a.sidand w.sid = b.sidand w.con_id=p.con_id and h.ctime > 901) loop
execute immediate v_find_obj_sql into v_objname using rec.obj_id,rec.con_id;
v_msg := rec.summary || chr(10) || 'Locked object :' || v_objname || chr(10) ||rec.details;
v_title := sys_context('USERENV','INSTANCE_NAME')||'_'||rec.pdbname||'_12c_oracle_15';
v_msg := v_msg || chr(10) || 'Additional sql text:'|| chr(10) ;
if rec.b_sql_id is not null then
v_msg := v_msg || chr(10) || rec.b_sql_id ||':'||chr(10) ||get_full_sqltext(rec.b_sql_id);
end if ;
if rec.w_sql_id is not null then
v_msg := v_msg || chr(10) || rec.w_sql_id ||':'||chr(10) ||get_full_sqltext(rec.w_sql_id);
end if ;
if rec.b_prev_sql_id is not null then
v_msg := v_msg || chr(10) || rec.b_prev_sql_id ||':'||chr(10) ||get_full_sqltext(rec.b_prev_sql_id);
end if ;
if rec.w_prev_sql_id is not null then
v_msg := v_msg || chr(10) || rec.w_prev_sql_id ||':'||chr(10) ||get_full_sqltext(rec.w_prev_sql_id);
end if ;
#dbms_output.put_line(v_msg) ;
#dbms_output.put_line(v_title) ;
#dbms_output.put_line(send_mail(v_title,v_msg)) ;
end loop ;
end;
/
exit;
这里单独取object name是因为再cdb里面不存储single pdb的 object 信息。
所以只能使用containers()函数获取。还需要注意的是,如果在plsql 块的sql里面使用containers函数会出现无法编译的情况,所以这里只能使用动态sql。
local_db_blocking_check_15.sh
#!/bin/bash
OLDPATH=$PATH
export PATH=$PATH:/usr/local/bin
SCRIPTDIR=/oracle/src/scripts/monitoring
SCANADDR=$(hostname | awk -F- '{print $1"-"$2"-"$3"-scan"}')
QWERTY=QAZ2wsx3edc
PORT=1521#echo date >> /tmp/blocking_monitoring.logfunction Role_Check {CONNECTTO=$1DB_ROLE=NONE# Database role check
DB_ROLE=$(sqlplus -s system/"${QWERTY}"@${SCANADDR}:${PORT}/${CONNECTTO} <<EOFset pagesize 0set heading offset feedback offSELECT database_role FROM v\$database;exit;
EOF
)}
ORACLE_SID=$(ps -eaf | grep -i smon | cut -d_ -f3 | grep +)# Use ORAENV_ASK set to NO to prevent prompting, but instead use the SID value set aboveORAENV_ASK=NO. oraenv for db_uniq in $(srvctl config database)
doRole_Check ${db_uniq}if [ "${DB_ROLE}" == "PRIMARY" ]; thensqlplus -s sys/"${QWERTY}"@${SCANADDR}:${PORT}/${db_uniq} as sysdba @${SCRIPTDIR}/BASE/blocking2.sql fi
done
这个就没什么好说的了。
最后只要把
local_db_blocking_check_15.sh
放到corntab 里面就可以了,一般是15分钟检查一次。如果要修改频率,记得再sql 里面修改h.ctime > 901 的 时间间隔。
最后注意两点:
- UTL_MAIL 记得开启权限
- 我们的scan addr是有规律的,所以如果要使用你们自己的环境记得修改这部分shell代码。
SCANADDR=$(hostname | awk -F- ‘{print $1"-"$2"-"$3"-scan"}’)
附录:
检查blocking脚本是类似于这样的:
select /*+ rule */'Container '||p.name||' Session '||a.sid||' is blokcing session '||b.sid||' by object '||o.owner || '.' || o.object_name ||nvl2 (subobject_name, '.' || subobject_name, null)||' duration: '|| lpad (to_char (trunc (w.ctime / 3600)), 3, '0') || ':' ||lpad (to_char (mod (trunc (w.ctime / 60), 60)), 2, '0') || ':' ||lpad (to_char (mod (w.ctime, 60)), 2, '0')||' Lock type ' ||h.type summary,
'Blocker SID :' || a.sid ||chr(10)||
'Blocker Username :' || a.username ||chr(10)||
'Blocker App Machine :' || a.machine ||chr(10)||
'Blocker Serial number :' || a.serial# ||chr(10)||
'Blocker Current Status :' || a.status ||chr(10)||
'Blocker SQL ID current :' || a.sql_id ||chr(10)||
'Blocker Previous SQL ID :' || a.prev_sql_id ||chr(10)||
'Blocker KCML Partition No :' || a.module ||chr(10)||
'Blocker Program name :' || a.program ||chr(10)||
'Blocker Client Information :' || a.client_info ||chr(10)||
'Blocker Application UUID :' || a.ecid ||chr(10)||
'Waiter SID :' || b.sid||chr(10)||
'Waiter Username :' || b.username ||chr(10)||
'Waiter App Machine :' || b.machine ||chr(10)||
'Waiter Serial number :' || b.serial# ||chr(10)||
'Waiter Current Status :' || b.status ||chr(10)||
'Waiter SQL ID current :' || b.sql_id ||chr(10)||
'Waiter Previous SQL ID :' || b.prev_sql_id ||chr(10)||
'Waiter KCML Partition No :' || b.module ||chr(10)||
'Waiter Program name :' || b.program ||chr(10)||
'Waiter Client Information :' || b.client_info ||chr(10)||
'Waiter Application UUID :' || b.ecid details,a.sql_id b_sql_id,a.prev_sql_id b_pre_sql_id,b.sql_id w_sql_id,b.prev_sql_id w_prev_sql_idfrom v$lock h, v$lock w, v$session b, v$session a, dba_objects o , v$pdbs pwhere h.block != 0and h.lmode != 0and h.lmode != 1and w.request != 0and w.id1 = h.id1and w.id2 = h.id2and h.sid = a.sidand w.sid = b.sidand decode (w.type, 'TX', b.row_wait_obj#,'TM', w.id1)= o.object_idand w.con_id=o.con_idand w.con_id=p.con_id
order by w.ctime desc;
以上sql适用于11g,如果是12c记得把获取object_name的部分去掉。
最后的效果类似于这样:
email title:
xxx-xxx-xxx-0101_1_xxxDB39_12c_oracle_15
body:
Container DB125439 Session 32787 is blokcing session 35500 duration: 000:47:33 Lock type TX Locked object :DEXTER.TESTTABLE
Blocker SID :32787
Blocker Username :DEXTER
Blocker App Machine :xxx-xxx-xxx-01
Blocker Serial number :44996
Blocker Current Status :INACTIVE
Blocker SQL ID current :
Blocker Previous SQL ID :cdvppfnyngumd
Blocker KCML Partition No :SQL*Plus
Blocker Program name :sqlplus@xxx-xxx-xxx-01 (TNS V1-V3)
Blocker Client Information :
Blocker Application UUID :
Waiter SID :35500
Waiter Username :DEXTER
Waiter App Machine :xxx-xxx-xxx-01
Waiter Serial number :18786
Waiter Current Status :ACTIVE
Waiter SQL ID current :5z3w5m3z9yv6y
Waiter Previous SQL ID :cdvppfnyngumd
Waiter KCML Partition No :SQL*Plus
Waiter Program name :sqlplus@xxx-xxx-xxx-01 (TNS V1-V3)
Waiter Client Information :
Waiter Application UUID :
Additional sql text:xxxxxx:
update testtable set id=333 where id=3
xxxxxx:
update testtable set id=5
xxxxxx:
update testtable set id=5
敏感信息我就用xxx代替了
分享一个前两天写的自动监控blocking 的脚本(基于12C)相关推荐
- 分享一个前后端分离的轻量级内容管理框架
开发框架要考虑的面太多了:安全.稳定.性能.效率.扩展.整洁,还要经得起实践的考验,从零开发一个可用的框架,是很耗时费神的工作.网上很多开源的框架,为何还要自己开发?我是基于以下两点: 没找到合适的: ...
- 分享一个四两拨千斤的真实故事
分享一个四两拨千斤的真实故事. 看懂的人都是当老板的料. 有一家小食品公司,辣椒酱上市前想做宣传,无奈没有太雄厚的经济实力,租不起市区广告牌. 于是,他们突发奇想,租下城门口的一个不值钱的广告牌. 租 ...
- 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi
一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...
- 用python写一个自动注册脚本_python写的自动登录人人网的脚本
我今天给大家分享一个我自己用 #!/usr/bin/env python #encoding=utf-8 import sys import re import urllib2 import urll ...
- 分享一个电影网站源码。自动抓取
分享一个电影网站源码.下面是演示地址,可能UI方面有些不同. www.qwdianying.top 下载地址:https://pan.baidu.com/s/1VU16AkklpCZ-tiPCAZ51 ...
- 分享一个自己利用Python写的淘宝秒杀工具源码
看论坛里有好多大神上传了秒杀神器,我是一个初学者,写了一段代码,但是根本实现不了毫秒级的秒杀,只能做到"秒点",但是无论如何,我也突破不了这个瓶颈,今天分享给大家,希望大家能给出一 ...
- 分享一个前后端分离的web项目(vue+spring boot)
Github地址:https://github.com/smallsnail-wh 前端项目名为wh-web 后端项目名为wh-server 项目展示地址为我的github pages(https:/ ...
- 分享一个强大的在线写API接口文档的工具showdoc
网站地址:https://www.showdoc.cc 第一步:注册 第二步:填写注册信息,这里填写用户名和密码即可,用户名不可重复,注册登录后可以绑定邮箱. 也可以不注册查看示例决定要不要使用这个网 ...
- python网址太长_【原创】分享一个自己用python写的长网址转短网址工具,给需要的你...
[Python] 纯文本查看 复制代码import requests import json from tkinter import * class Get_url_short(): def __in ...
最新文章
- linux(gentoo)安装配置conky
- rust(13)-闭包作为参数 trait泛型
- 1.VMwareTools的安装,vmware启动的时候,虚拟机黑屏,解决办法
- MyBatis 实践
- iPhone 14系列升级巨大:两款Pro版或将配置4800万像素镜头
- 阿里巴巴Java开发手册
- spring transactional 事务传播机制
- 计算机组成原理/计算机硬件基础第五章:存储器
- Set Scrolling Pictrues in the WebPage
- mysql data seek_mysql_data_seek函数详解
- MacBook Air 2013全新安装Win7
- phython入门开始
- 【Java实战小项目】考试系统
- 统计信号处理基础 习题解答5-8
- 《武则天正传》读后感
- Unittest-跳过
- 烤仔星选·NFT实验室 | 非同质化代币在游戏领域的应用
- 如何知道页面浏览时长系列之 Web 篇
- 1024分辨率《加勒比海盗4》BD中英双字无水印
- python static方法_浅谈python 类方法/静态方法