November 7, 2007
Streams流复制的异常检测
作者:eygle
出处:http://blog.eygle.com
在使用Streams流复制的过程中,遇到各种错误的时候很常见。在Oracle的文档(Oracle® Streams Concepts and Administration 10g Release 2 )上提供了一个异常检测方案。比如在LCR应用过程中出现错误:
SQL> select apply_name,LOCAL_TRANSACTION_ID,SOURCE_TRANSACTION_ID,ERROR_MESSAGE
2 from dba_apply_error;
APPLY_NAME LOCAL_TRANSACTION_ID SOURCE_TRANSACTION_ID ERROR_MESSAGE
----------- ---------------------- ---------------------- -------------------------
APP97_APPLY 5.27.1273 4.46.576 ORA-01403: no data found
对复制管理员进行授权:
SQL> GRANT SELECT ON DBA_APPLY_ERROR TO strmadmin;
Grant succeeded
SQL> GRANT EXECUTE ON DBMS_APPLY_ADM TO strmadmin;
Grant succeeded
此后需要建立几个过程
SQL> connect strmadmin/strmadmin@test97
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as strmadmin
SQL> CREATE OR REPLACE PROCEDURE print_any (DATA IN ANYDATA)
2 IS
3 tn VARCHAR2 (61);
4 str VARCHAR2 (4000);
5 CHR VARCHAR2 (1000);
6 num NUMBER;
7 dat DATE;
8 rw RAW (4000);
9 res NUMBER;
10 BEGIN
11 IF DATA IS NULL
12 THEN
13 DBMS_OUTPUT.put_line ('NULL value');
14 RETURN;
15 END IF;
16
17 tn := DATA.gettypename ();
18
19 IF tn = 'SYS.VARCHAR2'
20 THEN
21 res := DATA.getvarchar2 (str);
22 DBMS_OUTPUT.put_line (SUBSTR (str, 0, 253));
23 ELSIF tn = 'SYS.CHAR'
24 THEN
25 res := DATA.getchar (CHR);
26 DBMS_OUTPUT.put_line (SUBSTR (CHR, 0, 253));
27 ELSIF tn = 'SYS.VARCHAR'
28 THEN
29 res := DATA.getvarchar (CHR);
30 DBMS_OUTPUT.put_line (CHR);
31 ELSIF tn = 'SYS.NUMBER'
32 THEN
33 res := DATA.getnumber (num);
34 DBMS_OUTPUT.put_line (num);
35 ELSIF tn = 'SYS.DATE'
36 THEN
37 res := DATA.getdate (dat);
38 DBMS_OUTPUT.put_line (dat);
39 ELSIF tn = 'SYS.RAW'
40 THEN
41 -- res := data.GETRAW(rw);
42 -- DBMS_OUTPUT.PUT_LINE(SUBSTR(DBMS_LOB.SUBSTR(rw),0,253));
43 DBMS_OUTPUT.put_line ('BLOB Value');
44 ELSIF tn = 'SYS.BLOB'
45 THEN
46 DBMS_OUTPUT.put_line ('BLOB Found');
47 ELSE
48 DBMS_OUTPUT.put_line ('typename is ' || tn);
49 END IF;
50 END print_any;
51 /
Procedure created
SQL> CREATE OR REPLACE PROCEDURE print_lcr (lcr IN ANYDATA)
2 IS
3 typenm VARCHAR2 (61);
4 ddllcr SYS.lcr$_ddl_record;
5 proclcr SYS.lcr$_procedure_record;
6 rowlcr SYS.lcr$_row_record;
7 res NUMBER;
8 newlist SYS.lcr$_row_list;
9 oldlist SYS.lcr$_row_list;
10 ddl_text CLOB;
11 ext_attr ANYDATA;
12 BEGIN
13 typenm := lcr.gettypename ();
14 DBMS_OUTPUT.put_line ('type name: ' || typenm);
15
16 IF (typenm = 'SYS.LCR$_DDL_RECORD')
17 THEN
18 res := lcr.getobject (ddllcr);
19 DBMS_OUTPUT.put_line ( 'source database: '
20 || ddllcr.get_source_database_name
21 );
22 DBMS_OUTPUT.put_line ('owner: ' || ddllcr.get_object_owner);
23 DBMS_OUTPUT.put_line ('object: ' || ddllcr.get_object_name);
24 DBMS_OUTPUT.put_line ('is tag null: ' || ddllcr.is_null_tag);
25 DBMS_LOB.createtemporary (ddl_text, TRUE);
26 ddllcr.get_ddl_text (ddl_text);
27 DBMS_OUTPUT.put_line ('ddl: ' || ddl_text);
28 -- Print extra attributes in DDL LCR
29 ext_attr := ddllcr.get_extra_attribute ('serial#');
30
31 IF (ext_attr IS NOT NULL)
32 THEN
33 DBMS_OUTPUT.put_line ('serial#: ' || ext_attr.accessnumber ());
34 END IF;
35
36 ext_attr := ddllcr.get_extra_attribute ('session#');
37
38 IF (ext_attr IS NOT NULL)
39 THEN
40 DBMS_OUTPUT.put_line ('session#: ' || ext_attr.accessnumber ());
41 END IF;
42
43 ext_attr := ddllcr.get_extra_attribute ('thread#');
44
45 IF (ext_attr IS NOT NULL)
46 THEN
47 DBMS_OUTPUT.put_line ('thread#: ' || ext_attr.accessnumber ());
48 END IF;
49
50 ext_attr := ddllcr.get_extra_attribute ('tx_name');
51
52 IF (ext_attr IS NOT NULL)
53 THEN
54 DBMS_OUTPUT.put_line ( 'transaction name: '
55 || ext_attr.accessvarchar2 ()
56 );
57 END IF;
58
59 ext_attr := ddllcr.get_extra_attribute ('username');
60
61 IF (ext_attr IS NOT NULL)
62 THEN
63 DBMS_OUTPUT.put_line ('username: ' || ext_attr.accessvarchar2 ());
64 END IF;
65
66 DBMS_LOB.freetemporary (ddl_text);
67 ELSIF (typenm = 'SYS.LCR$_ROW_RECORD')
68 THEN
69 res := lcr.getobject (rowlcr);
70 DBMS_OUTPUT.put_line ( 'source database: '
71 || rowlcr.get_source_database_name
72 );
73 DBMS_OUTPUT.put_line ('owner: ' || rowlcr.get_object_owner);
74 DBMS_OUTPUT.put_line ('object: ' || rowlcr.get_object_name);
75 DBMS_OUTPUT.put_line ('is tag null: ' || rowlcr.is_null_tag);
76 DBMS_OUTPUT.put_line ('command_type: ' || rowlcr.get_command_type);
77 oldlist := rowlcr.get_values ('old');
78
79 FOR i IN 1 .. oldlist.COUNT
80 LOOP
81 IF oldlist (i) IS NOT NULL
82 THEN
83 DBMS_OUTPUT.put_line ('old(' || i || '): '
84 || oldlist (i).column_name
85 );
86 print_any (oldlist (i).DATA);
87 END IF;
88 END LOOP;
89
90 newlist := rowlcr.get_values ('new', 'n');
91
92 FOR i IN 1 .. newlist.COUNT
93 LOOP
94 IF newlist (i) IS NOT NULL
95 THEN
96 DBMS_OUTPUT.put_line ('new(' || i || '): '
97 || newlist (i).column_name
98 );
99 print_any (newlist (i).DATA);
100 END IF;
101 END LOOP;
102
103 -- Print extra attributes in row LCR
104 ext_attr := rowlcr.get_extra_attribute ('row_id');
105
106 IF (ext_attr IS NOT NULL)
107 THEN
108 DBMS_OUTPUT.put_line ('row_id: ' || ext_attr.accessurowid ());
109 END IF;
110
111 ext_attr := rowlcr.get_extra_attribute ('serial#');
112
113 IF (ext_attr IS NOT NULL)
114 THEN
115 DBMS_OUTPUT.put_line ('serial#: ' || ext_attr.accessnumber ());
116 END IF;
117
118 ext_attr := rowlcr.get_extra_attribute ('session#');
119
120 IF (ext_attr IS NOT NULL)
121 THEN
122 DBMS_OUTPUT.put_line ('session#: ' || ext_attr.accessnumber ());
123 END IF;
124
125 ext_attr := rowlcr.get_extra_attribute ('thread#');
126
127 IF (ext_attr IS NOT NULL)
128 THEN
129 DBMS_OUTPUT.put_line ('thread#: ' || ext_attr.accessnumber ());
130 END IF;
131
132 ext_attr := rowlcr.get_extra_attribute ('tx_name');
133
134 IF (ext_attr IS NOT NULL)
135 THEN
136 DBMS_OUTPUT.put_line ( 'transaction name: '
137 || ext_attr.accessvarchar2 ()
138 );
139 END IF;
140
141 ext_attr := rowlcr.get_extra_attribute ('username');
142
143 IF (ext_attr IS NOT NULL)
144 THEN
145 DBMS_OUTPUT.put_line ('username: ' || ext_attr.accessvarchar2 ());
146 END IF;
147 ELSE
148 DBMS_OUTPUT.put_line ('Non-LCR Message with type ' || typenm);
149 END IF;
150 END print_lcr;
151 /
Procedure created
SQL> CREATE OR REPLACE PROCEDURE print_errors
2 IS
3 CURSOR c
4 IS
5 SELECT local_transaction_id, source_database, message_number,
6 message_count, error_number, error_message
7 FROM dba_apply_error
8 ORDER BY source_database, source_commit_scn;
9
10 i NUMBER;
11 txnid VARCHAR2 (30);
12 SOURCE VARCHAR2 (128);
13 msgno NUMBER;
14 msgcnt NUMBER;
15 errnum NUMBER := 0;
16 errno NUMBER;
17 errmsg VARCHAR2 (255);
18 lcr ANYDATA;
19 r NUMBER;
20 BEGIN
21 FOR r IN c
22 LOOP
23 errnum := errnum + 1;
24 msgcnt := r.message_count;
25 txnid := r.local_transaction_id;
26 SOURCE := r.source_database;
27 msgno := r.message_number;
28 errno := r.error_number;
29 errmsg := r.error_message;
30 DBMS_OUTPUT.put_line
31 ('*************************************************');
32 DBMS_OUTPUT.put_line ('----- ERROR #' || errnum);
33 DBMS_OUTPUT.put_line ('----- Local Transaction ID: ' || txnid);
34 DBMS_OUTPUT.put_line ('----- Source Database: ' || SOURCE);
35 DBMS_OUTPUT.put_line ('----Error in Message: ' || msgno);
36 DBMS_OUTPUT.put_line ('----Error Number: ' || errno);
37 DBMS_OUTPUT.put_line ('----Message Text: ' || errmsg);
38
39 FOR i IN 1 .. msgcnt
40 LOOP
41 DBMS_OUTPUT.put_line ('--message: ' || i);
42 lcr := DBMS_APPLY_ADM.get_error_message (i, txnid);
43 print_lcr (lcr);
44 END LOOP;
45 END LOOP;
46 END print_errors;
47 /
Procedure created
现在就可以使用print_errors来打印出详细的错误信息,但是注意,如果错误事务非常多,那么这个过程可能会非常耗时:
SQL> SET SERVEROUTPUT ON SIZE 1000000
SQL> EXEC print_errors
*************************************************
----- ERROR #1
----- Local Transaction ID: 5.27.1273
----- Source Database: TEST201.EYGLE.COM
----Error in Message: 1
----Error Number: 1403
----Message Text: ORA-01403: no data found
--message: 1
type name: SYS.LCR$_ROW_RECORD
source database: TEST201.EYGLE.COM
owner: SCOTT
object: DEPT
is tag null: Y
command_type: UPDATE
old(1): DEPTNO
50
old(2): LOC
CHINA
new(1): LOC
CHINA
PL/SQL procedure successfully completed
最后创建一个print_transaction过程可以用来打印输出指定事务的详细信息:
SQL> CREATE OR REPLACE PROCEDURE print_transaction (ltxnid IN VARCHAR2)
2 IS
3 i NUMBER;
4 txnid VARCHAR2 (30);
5 SOURCE VARCHAR2 (128);
6 msgno NUMBER;
7 msgcnt NUMBER;
8 errno NUMBER;
9 errmsg VARCHAR2 (128);
10 lcr ANYDATA;
11 BEGIN
12 SELECT local_transaction_id, source_database, message_number,
13 message_count, error_number, error_message
14 INTO txnid, SOURCE, msgno,
15 msgcnt, errno, errmsg
16 FROM dba_apply_error
17 WHERE local_transaction_id = ltxnid;
18
19 DBMS_OUTPUT.put_line ('----- Local Transaction ID: ' || txnid);
20 DBMS_OUTPUT.put_line ('----- Source Database: ' || SOURCE);
21 DBMS_OUTPUT.put_line ('----Error in Message: ' || msgno);
22 DBMS_OUTPUT.put_line ('----Error Number: ' || errno);
23 DBMS_OUTPUT.put_line ('----Message Text: ' || errmsg);
24
25 FOR i IN 1 .. msgcnt
26 LOOP
27 DBMS_OUTPUT.put_line ('--message: ' || i);
28 lcr := DBMS_APPLY_ADM.get_error_message (i, txnid); -- gets the LCR
29 print_lcr (lcr);
30 END LOOP;
31 END print_transaction;
32 /
Procedure created
现在来看看这个失败的事务:
SQL> SET SERVEROUTPUT ON SIZE 1000000
SQL> EXEC print_transaction('5.27.1273')
----- Local Transaction ID: 5.27.1273
----- Source Database: TEST201.EYGLE.COM
----Error in Message: 1
----Error Number: 1403
----Message Text: ORA-01403: no data found
--message: 1
type name: SYS.LCR$_ROW_RECORD
source database: TEST201.EYGLE.COM
owner: SCOTT
object: DEPT
is tag null: Y
command_type: UPDATE
old(1): DEPTNO
50
old(2): LOC
CHINA
new(1): LOC
CHINA
PL/SQL procedure successfully completed
这几个过程在流复制的故障诊断中非常有用,记录于此。
-The End-
Posted by eygle at 10:41 AM | Comments (4)
wmiprvse.exe进程是什么?
作者:eygle
出处:http://blog.eygle.com
这几天注意到一个wmiprvse.exe进程,似乎影响了系统的启动速度。
以为是感染了病毒,研究一下这个进程:
正常情况下,wmiprvse.exe是Windows操作系统的一部分,存在位置为C:\system32\wbem\wmiprvse.exe。
其作用是通过WinMgmt.exe程序处理WMI操作,是一个关键进程。wmiprvse.exe WMI 包括对象储备库和 CIM 对象管理器。对象管理器负责处理储备库中对象的收集和操作并从WMI provider (在WMI 和操作系统、应用程序以及其他系统的组件之间充当中介)收集信息。简单来说,运行管理工具中的某个应用程序的时候,在系统进程管理中可以看到wmiprvse.exe进程。
看一下这个进程的起始位置:
D:\>tlist 2316
2316 wmiprvse.exe
CWD: D:\WINDOWS\system32\
CmdLine: D:\WINDOWS\system32\wbem\wmiprvse.exe
VirtualSize: 45288 KB PeakVirtualSize: 46616 KB
WorkingSetSize: 6956 KB PeakWorkingSetSize: 7112 KB
NumberOfThreads: 7
2320 Win32StartAddr:0x01024636 LastErr:0x000036b7 State:Waiting
2424 Win32StartAddr:0x5f9a1c49 LastErr:0x00000000 State:Waiting
2472 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Waiting
2476 Win32StartAddr:0x769ae429 LastErr:0x00000000 State:Waiting
2488 Win32StartAddr:0x0100ce42 LastErr:0x00000000 State:Waiting
2492 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Waiting
2876 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Waiting
5.1.2600.2180 shp 0x01000000 wmiprvse.exe
wmiprvse.exe 有可能会被病毒修改,如果不存在于上述目录中,则有可能是病毒文件(如用Visual C++编写的IRCBot蠕虫病毒就是一个例子)。
这样看来我的系统似乎又是正常的,唯一可疑的是,在正常运行下,这个进程也被启动了。
-The End-
Posted by eygle at 8:51 AM | Comments (7)
