分类目录归档:未分类

2009 –> 2010

2009马上就要飘走了,抓着它的尾巴来回顾一下去年的计划
1. 入门轮滑,游好自由泳
2. 去一趟云南,走元阳梯田-西双版纳,或者怒江-独龙江,去阳朔骑车
3. 把广东话和英语讲好一点
4. 看10本书
5. 写50篇blog
6. 照相像样一点
7. 养成耐心有效沟通的习惯,学会在工作中做决定
8. 深入学习工作用到的产品,oracle,tibco,unix
9. 把饭做好吃一点
10. 2009去医院的次数不超过3次(包含体检,挑鱼骨,拍牙片)
11. Anual dinner继续中奖,主要用来证明我的人品

一一解释
1. 轮滑是玩了几个月,没有去游泳,因为没心情没精力.轮滑10.1之后我基本没玩了,都改徒步了.
2. 最后10.1去了中甸和亚丁,玩得很开心.
3. 好像是讲得好了一点点了,不过现在出去聊天还是尽量用普通话聊天,避免有广东话出丑.
4. 把Oracle的书加起来就有5本了,非Oracle书籍中,最精彩的应该就是<<不去会死>>这本书了
5. 差不多是50篇,如果把校内上的日记算上的话
6. 拿了colin和Bob的相机玩了好几次,感觉还不错了。有钱了就自己买单反来玩。
7. 关于做决定,开始对production独立实施一些改变后,有了强烈的感受。这应该是今年最有价值的工作经验了,就是决断和对自己的信心。
8. 下半年开始专心学习Oracle,收获良多,下半年很多blog也是记录自己的一些学习碎片。
9. 我现在发展洗菜洗碗等简单的体力活了。
10. 不只3次,不过今年身体好多了。
11. Anual Dinner流产了。

相对于2008,2009还是过得好多了,记一下计划之外的东西
1. 虽然上半年工作上比较郁闷,不过后来争取了DBA的机会,下半年过得很充实。有两三月自己每个周末都到公司看书做实验,现在有了Metalink的帐号,相信明年会进步得更快。尤其是年尾自己独立在Production作了几次大的实施,对自己信心提升还是很大的.现在也可以逐渐冷静的面对各种问题.
2. 发展了徒步爬山,去了船底顶联布线,山野百里等活动,走了凤凰山8号线。这两个多月的高强度的活动让自己收获良多,也见识很多阳光的户外朋友。相对于轮滑或者自行车,徒步一起玩的人多,更多时间和队友聊天交流,还是更有意思.

展望一下2010吧
1. 希望家里人健康,这是一切的基础。今年年初娘做了直肠癌手术,那段时间呆在汕头半个月,压力很大,好在手术之后恢复比较好.
2. 在Oracle DBA职业上持续进步, 在态度上和技术上把自己整成一个职业人。每天可以坚持读10篇metalink上的文章,不放过每一个碰到的ORA-,主动和其他Team的人交流一起解决问题,踏踏实实的把技术做好,对得起自己的手艺.
3. 一次长途旅行,青藏线-中尼公路-尼泊尔。没仰望过那里的山,没和青藏高原上的藏民喊过一声’扎西德勒’,没触摸过那里的风,没闻过那里空气的味道, 这是再多的照片和攻略都代替不了的.以后的事情很难说,趁现在有这个想法这个激情,去走自己想走的路吧, 给自己打打气,年轻的时候,应该有勇气做自己想做的事情. 先记下了,过完年应该会确定会不会成行。
4. 钱,希望能存点钱留作急用,像现在这样月光的状态太心慌了。

出发之前

下午下班去食堂吃饭在公司装5升水就可以出发了!

上个星期8号线自己脚后跟起的泡还没完全恢复,这是最担心的一点。如果再次磨破了,之后的行程就会很辛苦。

希望一切顺利,Bob的相机充好电了,这次我要把它带上。

9.29 亚丁小转山

昨天晚上睡觉时开始下雨了,还好夜里风和雨都没飘进来把我弄醒。更好的是,当我们早上4点钟出门的时候,天空挤满了让人感动的星星。在天亮走到洛绒牛场之前,我们总不是忍不住抬头仰望星空赞叹。

到了洛绒牛场时,前面的央迈勇开始浮现。恩,惊叹.

从洛绒牛场出发,路开始变得泥泞,应该前几天下了雨。到牛奶海要过5000米的垭口,怪不得这段路骑马要300大洋。一边是峭壁,让人觉得荒凉。

其实不久就到了看了牛奶海所在的山谷的。太阳照着流水反射白色的光,终于看到传说着珍珠般的牛奶海.

追上向导时,没想到他们已经开始午餐了。这才9点多啊,向导说我们体力不行,建议不要去五色海了。看起来很近,爬个坡就上去了。但是对后面的路又没把握,就决定不去了。干脆慢慢悠悠的吃起来高原午餐:罐头加青稞饼.

接下来又时爬坡,都是灰色的砂石和山头。Jason开始发飙,一个人在前面速度走掉。这样我后面三个就有压力了,其实啊,总觉的一个团队一起走,不要拉的太远了,对后面的队友是一种压力。
下垭口时碰到一对人马,有十几个人吧,徒步去忽牯湖。
左边是层叠的地狱谷,离白云很近很近.

开始的冲锋最后的哑口,真的累了,一步一步的走着。刹车王一个人在前面,Bob显然陪我慢慢走着。Jason脚好像起泡了。看得出来好辛苦,一步一步的走着,走一段休息一段。我们在上面喊向导帮Jason把包背了,jason不肯。到最后下山,都是一步一步走下来。

哑口好多的经幡,拍了几张照,等Jason上来。

下山没多久,山上就飘起了小雪,昨天从珍珠海下来也飘雪了。慢慢的走着,以为一下就到了珍珠海了,没想到走了好远。最后一个下坡,把人走得绝望。

使用append hint 减少undo的产生

sid@CS10G> @mystat "undo change vector size"
sid@CS10G> set echo off

NAME                                VALUE
------------------------------ ----------
undo change vector size         154481820

sid@CS10G> insert into t select * from all_objects

49654 rows created.

sid@CS10G> commit;

Commit complete.

sid@CS10G> @mystat2
sid@CS10G> set echo off

NAME                                    V DIFF
------------------------------ ---------- ------------------
undo change vector size         154713576          231,756

sid@CS10G> @mystat "undo change vector size"
sid@CS10G> set echo off

NAME                                VALUE
------------------------------ ----------
undo change vector size         154713576

sid@CS10G> insert /*+ append */ into t select * from all_objects;

49654 rows created.

sid@CS10G> commit;

Commit complete.

sid@CS10G> @mystat2
sid@CS10G> set echo off

NAME                                    V DIFF
------------------------------ ---------- ------------------
undo change vector size         154719336            5,760

p.s: undo减少了,redo log也减少了

object types not in all_objects

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE    10.2.0.3.0      Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

SQL> select  object_type from (select * from dba_objects minus select * from all_objects) group by object_type;

OBJECT_TYPE
-------------------
QUEUE
DATABASE LINK
LOB

猜想是因为不能对这三种object进行直接的grant,不包含在All_objects里
从$ORACLE_HOME/rdbms/admin/catalog.sql对比发现dba_objects多了union all “database link”的select, all_objects多了一些where的条件
左: all_objects
右: dba_objects

    and                                                           |  union all                                                      
    (                                                             |  select u.name, l.name, NULL, to_number(null), to_number(null), 
      o.owner# in (userenv('SCHEMAID'), 1 /* PUBLIC */)           |         'DATABASE LINK',                                        
      or                                                          |         l.ctime, to_date(null), NULL, 'VALID','N','N', 'N'      
      (                                                           |  from sys.link$ l, sys.user$ u                                  
        /* EXECUTE privilege does not let user see package/type bo|  where l.owner# = u.user#                                       

gather db space usage statistics

除了owner不是sys(像undo/Temp/system/sysaux tablespace)的所有segments和tablespaces。
1. 输出segment的name,owner,type,initial extent, next exent, total size, used size, Util Status.
2. tablespace的使用率
3. db的使用率

set echo off
set heading on
set feedback off
set verify off
SET SERVEROUT ON size unlimited;
SET LINESIZE 180;

DECLARE
ttl_blks NUMBER := 0;
ttl_byte NUMBER := 0;
uus_blks NUMBER := 0;
uus_byte NUMBER := 0;
les_file NUMBER := 0;
les_blks NUMBER := 0; 
lus_blks NUMBER := 0;
grand_phys NUMBER := 0;
grand_byte NUMBER := 0;
grand_spac NUMBER := 0;
tblspc_phys NUMBER := 0;
tblspc_byte NUMBER := 0;
tblspc_spac NUMBER := 0;
wk_tblspc   VARCHAR2(256) := NULL;

CURSOR SEG IS
SELECT OWNER OWNER, SEGMENT_NAME SEGNAME, SEGMENT_TYPE SEGTYPE, BYTES SEGSIZE,
INITIAL_EXTENT SEGINIT, NVL(NEXT_EXTENT,0) SEGNEXT, EXTENTS SEGEXT,
TABLESPACE_NAME TBLSPC
FROM   DBA_SEGMENTS
WHERE  
OWNER not like  'SYS%'
--  TABLESPACE_NAME = 'ORABPEL'
ORDER  BY TABLESPACE_NAME, OWNER, SEGMENT_NAME;

rec_seg SEG%rowtype;

FUNCTION SIZETEXT (pi_size IN NUMBER, pi_textsize IN NUMBER DEFAULT 1024) RETURN VARCHAR2 IS
BEGIN
	--DBMS_OUTPUT.NEW_LINE;
	--DBMS_OUTPUT.PUT_LINE('wk_tblspc: '|| wk_tblspc );
	--DBMS_OUTPUT.PUT('segment_name: '|| segment_name );
	--DBMS_OUTPUT.PUT('pi_size: '|| pi_size );
	--DBMS_OUTPUT.PUT('pi_textsize: ' || pi_textsize );
	--DBMS_OUTPUT.NEW_LINE;
	--DBMS_OUTPUT.NEW_LINE;
	IF pi_size >= pi_textsize
		THEN
		RETURN SIZETEXT (pi_size, pi_textsize * 1024);
	END IF;
	IF pi_textsize = 1024
		THEN
		RETURN TO_CHAR(pi_size)||'b';
	ELSIF pi_textsize = 1024 * 1024
		THEN
		RETURN TO_CHAR(ROUND(pi_size*1024/pi_textsize,2))||'K';
	ELSIF pi_textsize = 1024 * 1024 * 1024
		THEN
		RETURN TO_CHAR(ROUND(pi_size*1024/pi_textsize,2))||'M';
	ELSIF pi_textsize = 1099511627776
		THEN
		RETURN TO_CHAR(ROUND(pi_size*1024/pi_textsize,2))||'G';
	ELSIF pi_textsize = 1125899906842624
		THEN
		RETURN TO_CHAR(ROUND(pi_size*1024/pi_textsize,2))||'T';
	END IF;
END SIZETEXT;

FUNCTION BAR (pi_used  IN NUMBER, 
	pi_total IN NUMBER, 
	pi_phys  IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
SCALE NUMBER := 10;
BEGIN
	RETURN RPAD(
		NVL(
			RPAD(
				NVL(LPAD('#',ROUND(pi_used/NVL(pi_phys,pi_total)*scale),'#'),
					'+'),
				ROUND(pi_total/NVL(pi_phys,pi_total)*scale),'+'),
			'-'), scale, '-')||
	' '||ROUND(pi_used/NVL(pi_phys,pi_total)*100,2)||'%';
END BAR;

BEGIN

	DBMS_OUTPUT.PUT_LINE('Report: Database Segment Size');
	DBMS_OUTPUT.PUT_LINE('Date  : '||to_char(sysdate,'DAY DD-MON-YYYY HH24:MI:SS'));
	DBMS_OUTPUT.PUT_LINE('Owner :'||rec_seg.owner );
	DBMS_OUTPUT.PUT(RPAD('Segment Name',35));
	DBMS_OUTPUT.PUT(RPAD('Owner',20));
	DBMS_OUTPUT.PUT(RPAD('Type',6));
	DBMS_OUTPUT.PUT(RPAD('Initial',9));
	DBMS_OUTPUT.PUT(RPAD('Next',9));
	DBMS_OUTPUT.PUT(RPAD('Exts',6));
	DBMS_OUTPUT.PUT(RPAD('TTL Sz',12));
	DBMS_OUTPUT.PUT(RPAD('Used Sz',12));
	DBMS_OUTPUT.PUT(RPAD('Util Status',20));
	DBMS_OUTPUT.NEW_LINE;

	DBMS_OUTPUT.PUT(LPAD(' ',35,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',20,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',6,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',9,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',9,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',6,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',12,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',12,'-'));
	DBMS_OUTPUT.PUT(LPAD(' ',20,'-'));
	DBMS_OUTPUT.NEW_LINE;

	OPEN SEG;
	LOOP
		FETCH SEG INTO rec_seg;
		EXIT WHEN SEG%NOTFOUND;
		IF wk_tblspc IS NULL 
			THEN
			SELECT SUM(BYTES)
			INTO   tblspc_phys
			FROM   DBA_DATA_FILES
			WHERE  TABLESPACE_NAME = rec_seg.TBLSPC;

			DBMS_OUTPUT.PUT_LINE('TABLESPACE: '||rec_seg.TBLSPC);
			wk_tblspc   := rec_seg.TBLSPC;
			tblspc_byte := 0;
			tblspc_spac := 0;
		ELSIF rec_seg.TBLSPC != wk_tblspc
			THEN
			DBMS_OUTPUT.PUT_LINE(RPAD('-',142,'-'));
			DBMS_OUTPUT.PUT(RPAD('Tablespace Total:',35));
			DBMS_OUTPUT.PUT(RPAD(sizetext(tblspc_phys),29));
			DBMS_OUTPUT.PUT(LPAD(sizetext(tblspc_byte),29));
			DBMS_OUTPUT.PUT(LPAD(sizetext(tblspc_byte - tblspc_spac),9));
			DBMS_OUTPUT.PUT(' '||bar(tblspc_byte-tblspc_spac,tblspc_byte,tblspc_phys));
			DBMS_OUTPUT.NEW_LINE;
			DBMS_OUTPUT.PUT_LINE(RPAD('-',142,'-'));
			DBMS_OUTPUT.PUT_LINE('TABLESPACE: '||rec_seg.TBLSPC);
			wk_tblspc   := rec_seg.TBLSPC;
			grand_byte  := grand_byte + tblspc_byte;
			grand_spac  := grand_spac + tblspc_spac;
			grand_phys  := grand_phys + tblspc_phys;
			tblspc_byte := 0;
			tblspc_spac := 0;

			SELECT SUM(BYTES)
			INTO   tblspc_phys
			FROM   DBA_DATA_FILES
			WHERE  TABLESPACE_NAME = rec_seg.TBLSPC;
		END IF;        

		DBMS_OUTPUT.PUT(RPAD(rec_seg.segname,35));
		DBMS_OUTPUT.PUT(RPAD(rec_seg.owner,20));
		DBMS_OUTPUT.PUT(RPAD(rec_seg.segtype,5));
		DBMS_OUTPUT.PUT(LPAD(sizetext(rec_seg.seginit),9));
		DBMS_OUTPUT.PUT(LPAD(sizetext(rec_seg.segnext),9));
		DBMS_OUTPUT.PUT(LPAD(rec_seg.segext,6));

		IF rec_seg.segtype = 'LOBSEGMENT'
			THEN
			DBMS_SPACE.UNUSED_SPACE(rec_seg.owner, rec_seg.segname, 'LOB',
				ttl_blks, ttl_byte, uus_blks, uus_byte,
				les_file, les_blks, lus_blks);
		ELSIF rec_seg.segtype IN ('TABLE','INDEX')
			THEN
			DBMS_SPACE.UNUSED_SPACE(rec_seg.owner, rec_seg.segname, rec_seg.segtype,
				ttl_blks, ttl_byte, uus_blks, uus_byte,
				les_file, les_blks, lus_blks);
		ELSE
			ttl_byte := rec_seg.segsize;
			uus_byte := 0;
		END IF;
		tblspc_byte := tblspc_byte + ttl_byte;
		tblspc_spac := tblspc_spac + uus_byte;    
		DBMS_OUTPUT.PUT(LPAD(sizetext(ttl_byte),12));
		DBMS_OUTPUT.PUT(LPAD(sizetext(ttl_byte - uus_byte),12));
		DBMS_OUTPUT.PUT(' '||bar(ttl_byte-uus_byte,ttl_byte));
		DBMS_OUTPUT.NEW_LINE;
	END LOOP;

	DBMS_OUTPUT.PUT_LINE(RPAD('-',142,'-'));
	DBMS_OUTPUT.PUT(RPAD('Tablespace Total:',35));
	DBMS_OUTPUT.PUT(RPAD(sizetext(tblspc_phys),29));
	DBMS_OUTPUT.PUT(LPAD(sizetext(tblspc_byte),29));
	DBMS_OUTPUT.PUT(LPAD(sizetext(tblspc_byte - tblspc_spac),12));
	DBMS_OUTPUT.PUT(' '||bar(tblspc_byte-tblspc_spac,tblspc_byte,tblspc_phys));
	DBMS_OUTPUT.NEW_LINE;
	DBMS_OUTPUT.PUT_LINE(RPAD('-',142,'-'));

	grand_byte  := grand_byte + tblspc_byte;
	grand_spac  := grand_spac + tblspc_spac;
	grand_phys  := grand_phys + tblspc_phys;

	DBMS_OUTPUT.PUT(RPAD('Grand Total:',35));
	DBMS_OUTPUT.PUT(RPAD(sizetext(grand_phys),29));
	DBMS_OUTPUT.PUT(LPAD(sizetext(grand_byte),29));
	DBMS_OUTPUT.PUT(LPAD(sizetext(grand_byte - grand_spac),12));
	DBMS_OUTPUT.PUT(' '||bar(grand_byte-grand_spac,grand_byte,grand_phys));
	DBMS_OUTPUT.NEW_LINE;
	DBMS_OUTPUT.PUT_LINE(RPAD('=',142,'='));
END;
/

输出例子,+/-/# 三个符号分别代表
#:已经分配segment并且使用的空间
+:已经分配segment还没使用的空间
-:空闲在datafile没分配给segment的空间

Segment Name                       Owner               Type  Initial  Next     Exts  TTL Sz      Used Sz     Util Status        
----------------------------------------------------------------------------------------------------------------------------------------------
TABLESPACE: TRY
BIG_TABLE                          SID                 TABLE      64K       0b    83         96M      90.76M #########+ 94.54%
T                                  SID                 TABLE      64K       0b    23          8M          8M ########## 100%
----------------------------------------------------------------------------------------------------------------------------------------------
Tablespace Total:                  200M                                                  104M      98.76M #####----- 49.38%
----------------------------------------------------------------------------------------------------------------------------------------------
Grand Total:                       2.02G                                              281.75M      238.7M #--------- 11.56%
==============================================================================================================================================

avoid number overflow in pl/sql

failed with number overflow:

  1  declare
  2  l_n number :=0 ;
  3  begin
  4  l_n := 1024*1024*1024*1024;
  5  --select 1024*1024*1024*1024 into l_n from dual;
  6  dbms_output.put_line(to_char(l_n,'999,999,999,999'));
  7* end;
sid@CS10G> /
declare
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 4

success

  1  declare
  2  l_n number :=0 ;
  3  begin
  4  --l_n := 1024*1024*1024*1024;
  5  select 1024*1024*1024*1024 into l_n from dual;
  6  dbms_output.put_line(to_char(l_n,'999,999,999,999,999'));
  7* end;
sid@CS10G> /
1,099,511,627,776

PL/SQL procedure successfully completed.

an example to check history event and statistics

最近DB的system Write I/O出了问题,启动emc mirrorview用sync模式复制local的数据到DR site之后, log file sync event从正常的3~6ms增加到30ms左右。

通过dba_hist_system_event 和dba_hist_sysstat 来收集这个星期的主要的write i/o参数,和对应时间的loading(通过每秒产生的redo size来衡量)

set pagesize 1000
set linesize 1000
set trimspool on

col event_name for A30
col wait_class for A20
col stat_name for A20

select a.snap_id, to_char(b.begin_interval_time,'yyyy-mm-dd hh24:mi:ss') snap_time, event_name, wait_class, TOTAL_WAITS-lag(TOTAL_WAITS) over (partition by event_name order by event_name, a.snap_id) waits, TIME_WAITED_MICRO-lag(TIME_WAITED_MICRO) over (partition by event_name order by event_name, a.snap_id) wait_time,
round((TIME_WAITED_MICRO-lag(TIME_WAITED_MICRO) over (partition by event_name order by event_name, a.snap_id))/(TOTAL_WAITS-lag(TOTAL_WAITS) over (partition by event_name order by event_name, a.snap_id))/1000) "Avg wait Time(ms)"
from dba_hist_system_event a, dba_hist_snapshot b
where event_name in ('log file sync','log file parallel write','db file parallel write','control file parallel write') and a.instance_number=2 
and a.snap_id = b.snap_id
and a.instance_number = b.instance_number
order by event_name, a.snap_id
/


select a.snap_id, to_char(b.begin_interval_time,'yyyy-mm-dd hh24:mi:ss') snap_time, a.stat_name, round((a.value-lag(a.value) over (partition by a.stat_name order by a.stat_name,a.snap_id))/3600)  "redo size byes/per second"
from dba_hist_sysstat a, dba_hist_snapshot b
where a.stat_name like '%redo size%' 
and a.instance_number = 2
and a.snap_id = b.snap_id
and a.instance_number = b.instance_number
order by a.snap_id 
/

sql的output如下

 SNAP_ID SNAP_TIME           EVENT_NAME                     WAIT_CLASS                WAITS  WAIT_TIME Avg wait Time(ms)
---------- ------------------- ------------------------------ -------------------- ---------- ---------- -----------------
     15464 2009-10-19 16:00:01 control file parallel write    System I/O
     15465 2009-10-19 17:00:08 control file parallel write    System I/O                 1852   15266978                 8
     15469 2009-10-19 21:00:01 control file parallel write    System I/O                 7213   64777026                 9


   SNAP_ID SNAP_TIME           STAT_NAME            redo size byes/per second
---------- ------------------- -------------------- -------------------------
     15464 2009-10-19 16:00:01 redo size
     15465 2009-10-19 17:00:08 redo size                              3360444
     15469 2009-10-19 21:00:01 redo size                              4522494
     15470 2009-10-19 22:00:10 redo size                              2277082
     15503 2009-10-21 07:00:03 redo size                             50265877
     15504 2009-10-21 08:00:16 redo size                              1723017
     15505 2009-10-21 09:00:26 redo size                              3134898

在此的基础用Excel生成报告,可以清晰的看到mirrorview对系统的影响