闲话不说直接上脚本。
用于再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 的 时间间隔。

最后注意两点:

  1. UTL_MAIL 记得开启权限
  2. 我们的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)相关推荐

  1. 分享一个前后端分离的轻量级内容管理框架

    开发框架要考虑的面太多了:安全.稳定.性能.效率.扩展.整洁,还要经得起实践的考验,从零开发一个可用的框架,是很耗时费神的工作.网上很多开源的框架,为何还要自己开发?我是基于以下两点: 没找到合适的: ...

  2. 分享一个四两拨千斤的真实故事

    分享一个四两拨千斤的真实故事. 看懂的人都是当老板的料. 有一家小食品公司,辣椒酱上市前想做宣传,无奈没有太雄厚的经济实力,租不起市区广告牌. 于是,他们突发奇想,租下城门口的一个不值钱的广告牌. 租 ...

  3. 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi

    一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...

  4. 用python写一个自动注册脚本_python写的自动登录人人网的脚本

    我今天给大家分享一个我自己用 #!/usr/bin/env python #encoding=utf-8 import sys import re import urllib2 import urll ...

  5. 分享一个电影网站源码。自动抓取

    分享一个电影网站源码.下面是演示地址,可能UI方面有些不同. www.qwdianying.top 下载地址:https://pan.baidu.com/s/1VU16AkklpCZ-tiPCAZ51 ...

  6. 分享一个自己利用Python写的淘宝秒杀工具源码

    看论坛里有好多大神上传了秒杀神器,我是一个初学者,写了一段代码,但是根本实现不了毫秒级的秒杀,只能做到"秒点",但是无论如何,我也突破不了这个瓶颈,今天分享给大家,希望大家能给出一 ...

  7. 分享一个前后端分离的web项目(vue+spring boot)

    Github地址:https://github.com/smallsnail-wh 前端项目名为wh-web 后端项目名为wh-server 项目展示地址为我的github pages(https:/ ...

  8. 分享一个强大的在线写API接口文档的工具showdoc

    网站地址:https://www.showdoc.cc 第一步:注册 第二步:填写注册信息,这里填写用户名和密码即可,用户名不可重复,注册登录后可以绑定邮箱. 也可以不注册查看示例决定要不要使用这个网 ...

  9. python网址太长_【原创】分享一个自己用python写的长网址转短网址工具,给需要的你...

    [Python] 纯文本查看 复制代码import requests import json from tkinter import * class Get_url_short(): def __in ...

最新文章

  1. 优化营商环境建议个人_优化营商环境的几点建议(三)
  2. 文件到Java中的byte []
  3. C语言 读取字符串数组中的字符串并获取字符串的长度
  4. 药理学css概念,药理学css 名词解释
  5. java里 currenttime_java 获取当前时间LocalDateTime currentTimeMillis java.util.Date
  6. python log函数_python要点-装饰器
  7. 软件工程师的6年总结
  8. 10.Object类
  9. 计算机网络(八)-数据链路层-帧封装
  10. ZBlog菜鸟精致灰黑简约风格MiNi主题
  11. matlab数字信号处理 王彬,MATLAB数字信号处理
  12. java 线程 condition_Java编程中实现Condition控制线程通信
  13. WampServer2.0的Apache的service无法启动的解决方法
  14. 【服务器】微信小程序转qq小程序
  15. 过程FMEA:失效模式/失效起因的理论+实例
  16. 数字华容道的数学原理
  17. 路由器如何设置无线桥接
  18. window7 右下角图标消失解决方法
  19. noip2012 pj错题整理
  20. [BZOJ3993] [SDOI2015]星际战争(最大流+二分)

热门文章

  1. 使用httpie快速访问https协议站点
  2. 拦截器重定向页面 设置不在 iframe中显示
  3. 贪吃蛇大作战撞墙不死c语言,贪吃蛇大作战无敌版
  4. 「一本通 6.5 例 4」佳佳的 Fibonacci
  5. 小梅哥FPGA学习笔记——状态机设计学习
  6. Tenth season second episode,Ross is fine about Rachel and Joey?Chandler and Monica e going to adopt?
  7. 使用python进行数据分析之电影评分
  8. Windows_U盘_SD卡_硬盘等存储介质无法完成格式化
  9. 基于深度学习的遥感影像语义分割数据预处理
  10. The global shader cache file'X:/XXXX/GlobalShaderCache-PCD3D_SM5.bin' is missing——UE4工程运行失败