【续篇】在Oracle的DG环境中,由于配置了登陆触发器导致日志不能同步,报错ORA-16191的实验验证总结

教育   2024-08-20 21:56   陕西  

上一篇

在Oracle的DG环境中,由于配置了登陆触发器导致日志不能同步,报错ORA-16191的实验验证总结

在上篇中,我们实验了一下,在DG环境中,若存在登陆触发器,则会导致Redo日志不能传递到备库从而报ora-16191的错误,解决办法也很简单,禁用相关触发器或者配置隐含参数

1ALTER SYSTEM SET "_system_trig_enabled"=FALSE sid='*';

然后重启库,或重新激活同步都可以。

但,在DG场景下,若领导要求必须有登陆日志的话,怎么办呢?

我们继续往下看。。。

若一定需要使用系统触发器呢?

若因为安全审计等原因,领导要求一定需要有该程序,那应该怎么办呢?

其实报错的主要原因是因为触发器中有dml操作,但物理备库是只读的,所以会报错,我们需要修改一下我们的程序。增加判断,若当前是主库,则直接插入表;若当前是备库,则需要通过dbalink插入到主库中或舍弃日志记录,具体根据领导要求来就行。

修改后的简单示例,如下,在主库执行即可:

  1drop table logon_audit_log;
2CREATE TABLE logon_audit_log (
3    id            NUMBER PRIMARY KEY,
4    username      VARCHAR2(30),
5    logon_time    date,
6    terminal      VARCHAR2(100),
7    osuser        VARCHAR2(30),
8    session_id    VARCHAR2(30),
9    host          VARCHAR2(100),
10    ip_address    VARCHAR2(45),
11    module        VARCHAR2(48),
12    actions       VARCHAR2(32),
13    db_role       VARCHAR2(32)       
14);
15
16insert into logon_audit_log (idvalues(1);
17commit;
18
19grant all on   sys.logon_audit_log to public;
20
21
22CREATE PUBLIC DATABASE LINK db_pri
23CONNECT TO system IDENTIFIED BY lhr
24USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.68.68)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = LHR11G)))';
25
26
27
28CREATE OR REPLACE TRIGGER logon_trigger
29AFTER LOGON ON DATABASE
30DECLARE
31    PRAGMA AUTONOMOUS_TRANSACTION;
32BEGIN
33
34
35
36  PRO_tri_logon();
37
38
39
40 EXCEPTION
41    WHEN OTHERS THEN
42       DBMS_SYSTEM.KSDWRT(2,SQLERRM);
43
44END;
45
46
47
48
49create or replace procedure PRO_tri_logon  AUTHID CURRENT_USER AS  
50
51       v_TERMINAL  varchar2(100);
52             v_OS_USER  varchar2(100);
53             v_SESSIONID  varchar2(100);
54             v_HOST  varchar2(100);
55             v_IP_ADDRESS  varchar2(100);
56             v_MODULE  varchar2(100);
57             v_ACTION    varchar2(100);  
58
59
60    v_db_role VARCHAR2(30);  
61    v_seq number;
62
63 begin   
64
65
66  SELECT DATABASE_ROLE INTO v_db_role FROM V$DATABASE;
67    select max(id)+1 into v_seq from sys.logon_audit_log;
68
69
70 IF v_db_role = 'PRIMARY' and USER not in ('SYS','PUBLIC','SYSTEM') THEN  
71
72    INSERT INTO sys.logon_audit_log (id,username, logon_time, terminal, osuser, session_id, host, ip_address, module, actions,db_role)
73    VALUES (
74        v_seq,
75        USER,
76        sysdate,
77        SYS_CONTEXT('USERENV''TERMINAL'),
78        SYS_CONTEXT('USERENV''OS_USER'),
79        SYS_CONTEXT('USERENV''SESSIONID'),
80        SYS_CONTEXT('USERENV''HOST'),
81        SYS_CONTEXT('USERENV''IP_ADDRESS'),
82        SYS_CONTEXT('USERENV''MODULE'),
83        SYS_CONTEXT('USERENV''ACTION'),
84        v_db_role
85    ); 
86        commit;     
87
88  elsif     USER not in ('SYS','PUBLIC','SYSTEM') THEN
89
90    select SYS_CONTEXT('USERENV''TERMINAL'),
91        SYS_CONTEXT('USERENV''OS_USER'),
92        SYS_CONTEXT('USERENV''SESSIONID'),
93        SYS_CONTEXT('USERENV''HOST'),
94        SYS_CONTEXT('USERENV''IP_ADDRESS'),
95        SYS_CONTEXT('USERENV''MODULE'),
96        SYS_CONTEXT('USERENV''ACTION'
97        into v_TERMINAL,v_OS_USER,v_SESSIONID,v_HOST,v_IP_ADDRESS,v_MODULE,v_ACTION
98   from dual;
99
100
101   EXECUTE IMMEDIATE 'INSERT INTO sys.logon_audit_log@db_pri (id,username, logon_time, terminal, osuser, session_id, host, ip_address, module, actions,db_role)
102    VALUES (
103        :v_seq,
104        USER,  sysdate,
105                :v_TERMINAL,:v_OS_USER,:v_SESSIONID,:v_HOST,:v_IP_ADDRESS,:v_MODULE,:v_ACTION,
106        :v_db_role
107    )'
 USING v_seq,v_TERMINAL,v_OS_USER,v_SESSIONID,v_HOST,v_IP_ADDRESS,v_MODULE,v_ACTION, v_db_role ;  
108
109        commit;
110
111  END IF;
112
113    commit;
114
115EXCEPTION
116    WHEN OTHERS THEN
117       DBMS_SYSTEM.KSDWRT(2,SQLERRM);
118
119end ;

主库做,启用触发器:

 1ALTER SYSTEM SET "_system_trig_enabled"=true sid='*';
2
3
4alter system set log_archive_dest_state_2='defer' sid='*';  
5alter system archive log current;
6alter system set log_archive_dest_state_2='ENABLE' sid='*';    
7alter system archive log current;
8
9
10
11SYS@LHR11G> SET PAGESIZE 9999
12SET LINE 9999
13COL NAME FORMAT A40
14COL KSPPDESC FORMAT A50
15COL KSPPSTVL FORMAT A20
16SELECT A.INDX,
17       A.KSPPINM NAME,
18       A.KSPPDESC,
19       B.KSPPSTVL
20
21FROM   X$KSPPI  A,
22       X$KSPPCV B
23WHERE  A.INDX = B.INDX
24AND A.KSPPINM LIKE '/_%' ESCAPE '/'
25AND LOWER(A.KSPPINM) LIKE  LOWER('_system_trig_enabled');
26
27
28      INDX NAME                                     KSPPDESC                                           KSPPSTVL
29---------- ---------------------------------------- -------------------------------------------------- --------------------
30      1876 _system_trig_enabled                     are system triggers enabled                        TRUE

备库做:

1ALTER SYSTEM SET "_system_trig_enabled"=true sid='*';
2
3
4alter database recover managed standby database cancel;  
5alter database recover managed standby database using current logfile disconnect from session;

然后使用lhr用户进行测试,日志可以正常记录:

做switchover验证

 1[oracle@lhr11gdg ~]$ dgmgrl  sys/lhr@lhr11g
2DGMGRL for Linux: Version 11.2.0.4.0 - 64bit Production
3
4Copyright (c) 2000, 2009, Oracle. All rights reserved.
5
6Welcome to DGMGRL, type "help" for information.
7Connected.
8DGMGRL> show configuration
9
10Configuration - LHR11G
11
12  Protection Mode: MaxPerformance
13  Databases:
14    LHR11G   - Primary database
15    LHR11GDG - Physical standby database
16
17Fast-Start Failover: DISABLED
18
19Configuration Status:
20SUCCESS
21DGMGRL> switchover to 'LHR11GDG';
22Performing switchover NOW, please wait...
23Operation requires a connection to instance "
LHR11GDG" on database "LHR11GDG"
24Connecting to instance "
LHR11GDG"...
25Connected.
26New primary database "
LHR11GDG" is opening...
27Operation requires startup of instance "
LHR11G" on database "LHR11G"
28Starting instance "
LHR11G"...
29ORACLE instance started.
30Database mounted.
31Database opened.
32Switchover succeeded, new primary is "
LHR11GDG"
33DGMGRL> show configuration
34
35Configuration - LHR11G
36
37  Protection Mode: MaxPerformance
38  Databases:
39    LHR11GDG - Primary database
40    LHR11G   - Physical standby database
41
42Fast-Start Failover: DISABLED
43
44Configuration Status:
45SUCCESS
46
47DGMGRL> 
48

switchover正常,但是在做了switchover后,备库到主库的dblink就得修改了,否则备库的登陆日志不能被记录的:

1DROP PUBLIC DATABASE LINK db_pri;
2CREATE PUBLIC DATABASE LINK db_pri
3CONNECT TO system IDENTIFIED BY lhr
4USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.68.69)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = LHR11GDG)))';

继续切换一次:

 1DGMGRL> switchover to 'LHR11G';
2Performing switchover NOW, please wait...
3Operation requires a connection to instance "LHR11G" on database "LHR11G"
4Connecting to instance "LHR11G"...
5Connected.
6New primary database "LHR11G" is opening...
7Operation requires startup of instance "LHR11GDG" on database "LHR11GDG"
8Starting instance "LHR11GDG"...
9ORACLE instance started.
10Database mounted.
11Database opened.
12Switchover succeeded, new primary is "LHR11G"
13DGMGRL> 
14DGMGRL> 
15DGMGRL> 
16DGMGRL> 
17DGMGRL> show configuration
18
19Configuration - LHR11G
20
21  Protection Mode: MaxPerformance
22  Databases:
23    LHR11G   - Primary database
24    LHR11GDG - Physical standby database
25
26Fast-Start Failover: DISABLED
27
28Configuration Status:
29SUCCESS
30
31DGMGRL> 

总结

1、可配置16191的events进行跟踪。

2、ora-16191常见原因有密码文件不同步、有登录触发器,不常见原因有传输的用户缺少sysoper角色。

3、若有系统登陆触发器,则需要禁掉该功能(在11.2.0.4中已复现)。

4、DG中不能同步的时候,可选择重启数据库,让某些配置生效(虽然参数已生效,但只有重启DB才能触发)。

5、使用系统触发器时,一定要慎重。在测试环境充分测试之后,再上生产环境。

6、11g环境中,不能在备库使用主库的序列;从12c开始,ADG可以使用主库创建的序列。

7、在触发器或存储过程中,可以使用DBMS_SYSTEM.KSDWRT(2,SQLERRM);将相关错误信息打印到告警日志中从而进行排错。





AiDBA
【PostgreSQL培训认证】【Oracle OCP、OCM、高可用(RAC+DG+OGG)培训认证】【MySQL OCP培训认证】【GreenPlum培训】【SQL Server培训】官网:www.dbaup.com,学习不止数据库
 最新文章