Oracle DRM 问题初探

ae7e479203b283defc6ab6417d5a2fef.gif

作者 | JiekeXu

来源 |公众号 JiekeXu DBA之路(ID: JiekeXu_IT)

如需转载请联系授权 | (个人微信 ID:JiekeXu_DBA)

大家好,我是 JiekeXu,很高兴又和大家见面了,今天和大家一起来看看 Oracle DRM 问题初探,欢迎点击上方蓝字“JiekeXu DBA之路”关注我的公众号,标星或置顶,更多干货第一时间到达!

目  录

DRM 简介
DRM 原理简介
DRM 主要功能
DRM 基本步骤
DRM 的利弊
DRM 应用场景
DRM 应用案例
关闭/禁止 DRM
验证 DRM 是否关闭
参考链接
附录 DRMDIAG.SQL


1、DRM 简介

Oracle DRM (Dynamic Resource management)即动态资源管理。 使用 RAC 时,每个实例都有自己的 SGA 和缓冲区。RAC 会修改这些 buffer,缓冲区的 buffer 也是一种资源,它有一个主节点,主节点是集群的节点之一。

当访问大量的 buffer master 不在本地节点时,会与 master buffer 节点产生多次通讯以及数据交互,如果可以通过一定的规则,让 master 在本地节点,就能减少这种跨节点申请 buffer 的操作,提高 RAC 性能。

Oracle 规则基于访问 Buffer 的频率,默认情况下,间隔 10 分钟,检查一下访问资源的节点次数,达到 1500 次之后,在对比 RAC 的节点次数,满足某个节点大于另一个节点访问的 50 倍差异后,并且这个节点并非这个资源的 master 节点,可以被 DRM 调整资源的 master 节点。

  • Oracle DRM 特性在 9i 出现雏形(file affinity)

  • Oracle DRM 在 10gR2 中得到改变

  • Oracle 11g DRM 细化不断增强

d63b8b7279aed66d47282811b3f9b659.png

9160fcbcc75909c26a9357fbb7d33142.png

ORACLE 11g 版本减少 DRM 给系统带来的影响 Oracle 进行了如下几处优化:
1.read-mostly locking(读多写少):简单的说就是,对于某个对象,比如读非常多,所有结点都会持有一个锁,减少了共享锁申请操作。而当需要写操作时,需申请排它锁时,在每个结点上都申请一个”anti-lock”锁,可以理解为”反锁”,然后再 cache fusion。
2.reader bypass(写少读多):主要是为读少写多的业务进行的优化。reader bypass 同样引入了一种新的锁模式 weak X lock(又称 xw 锁)。可以在 S 锁没有释放以前,为一个 block 加上一个 x w锁,对这个 block 进行修改,但是不允许立刻commit,直到所有的的 S 锁都关闭或者降级到N锁,LMS 就会向 xw 锁的持有者发送一条信息可以进行 commit 了。
3.Parallel DRM Freeze:在 DRM 发生的过程中会存在冻结阶段(Freeze),即所有节点的 LMS 进程在收到 LMON 发出的消息后,通知所有节点的 LMS 进程在结束 master 信息迁移前不再接受对这些快的新的请求。那么对于一个繁忙的系统这个过程是无法忍受的,因此 Oracle 引入了并行 DRM 加快 master 信息的迁移速度,使用 _drm_parallel_freeze 参数控制,默认情况下启用。
4.DRM Batch request:批量处理 DRM 请求使用参数 _lm_drm_batch_time 控制,默认为 10s。
5.DRM interval:增大 DRM 触发时间间隔,针对连续的 DRM 动作时间间隔至少为 120s,由参数 _lm_drm_min_interval 控制。
6.Read Mostly 数据固化:早先版本针对 DRM 的 ReadMostly 系统统计信息会随着实例的重启而被重置,为此从 11.2.0.3 版本开始,默认支持对 read mostly 的数据进行固化(通过 _gc_persistent_read_mostly 来实现)。
7.drm hiload:在数据库负载很高的情况下,会暂时禁用 DRM,数据库负载下降以后又重新启用 DRM,由参数 _lm_drm_hiload_percentage 和 _lm_drm_lowload_percentage 参数控制默认为 200。

下面首先对和 DRM 相关的一些概念进行介绍。

Buffer: 对于RAC 数据库,当一个数据块被读入到 buffer cache 后,我们就称其为 buffer , cache fusion 会将这个 buffer 作为 resource 来管理。

Master:在RAC 数据库的世界里,每一个 resource 都会有一个 master 实例,这个 master 实例会在 shared pool 中(例如:gcs resource 和 ges resource 部分)分配一些空间来存放和这个资源相关的信息,例如:哪一个实例拥有了这个 buffer 的最新版本,哪一个实例拥有了这个 buffer 的什么级别的 lock 等等。并且,负责维护和这个资源的状态。

2、DRM 原理简介

接下来,我们对 RAC 环境中,访问一个 buffer 的过程进行简单的描述。我们以一个 4 节点的 RAC 数据库为例。注意,我们只会列出比较典型的一种情况,不会把所有可能的情况都一一列出,而且只是把步骤进行了简单的介绍。

cf68fe82f37f6ca46d578586bcf2383c.png

步骤1:实例 3 需要以 X(exclusive)方式访问 buffer1, 向 master 实例 1 发出了请求。
步骤2:master 实例 1 发现实例 2 以 X 方式持有 buffer1,之后通知实例 2 释放 X lock,并把 buffer1 发送给实例 3。
步骤3: 实例 2 释放 X lock,并把最新版本的 buffer1 发送给实例 3。
步骤4:实例 3 获得 buffer1, 并通知 master 实例 1 更新资源 buffer1 的最新状态。

e816645f9eae4db33b11a15cf2393a83.png
从上面的步骤,我们不难看出,在 RAC 数据库中,当我们访问一个 buffer 的时候,最多会有 3 个实例参与其中,master 实例,holder(持有者)实例 和 requestor(申请者) 实例。2 种数据传输会出现,message:用于和 lock 相关的信息传输,data:用于传输 buffer。同时,根据上面的步骤我们也自然会想到,如果 master 和 requestor 在同一个实例上,那么就可以减少实例之间message 的传输并且访问的代码路径(code path)会更短,从而提高性能,但是每个 buffer 在被读取到 buffer cache 时,master 节点的选择是随机的。基于这种考虑, oracle 从 10g 开始,推出了一个新特性 DRM(Dynamic Resource management)

3、DRM 主要功能

DRM的主要功能是,根据一段时间内(默认 10 分钟),每个实例,对某一个数据库对象的 (10gR1 以数据文件为单位)的访问次数和方式,来决定数据库对象对应的 buffer 应该被 mastering 到哪一个实例。在指定时间内,如果某一个实例访问某个数据库对象次数高于其他实例一定倍数(默认 50 倍),则 oracle 会把这个对象所有的 buffer 的 master 信息,转移到对应实例(注意:不是转移 buffer)。当然,转移的过程是渐进式的。当 oracle 决定将一个 buffer 的 master 实例确定到本地实例后,会对这个buffer 上加上 affinity lock,来实现快速的访问。这也是我们经常提到的 object affinity 的由来。

4、DRM 基本步骤

接下来,我们对 DRM 的基本步骤进行介绍。
1. Oracle 停止所有在需要进行 remastering 的 buffer 上的操作。注意:DRM 是渐进的,也就是说以 windows 为单位,每次对一部分的 buffer 进行 remastering 操作。
2. Lmon 通知所有实例,准备进行 remastering
3. 在旧的 master 实例清除对应 buffer 的 master 信息
4. 将 master 信息传递给新的 master 实例
5. 在新的 master 实例构建资源的最新状态
6. 结束,并释放所有之前所有步骤占用的资源。

然后,我们对 DRM 相关的一些参数进行简单的介绍。
_gc_policy_time :单位为分钟,控制 DRM 统计实例访问 buffer 次数的时间间隔,默认为是 10 分钟。
_gc_affinity_ratio:控制进行 remastering 所需要达到的最小比例(阀值),默认为 50。也就是说,如果某个实例在 10 分钟(_gc_policy_time)之内,访问某个数据库对象的次数大于其他所有实例 50 倍时(注意:是 50 倍,而不是 50 次),对该数据库对象的 buffer 进行 remastering。

最后,如果您遇到了和 DRM 相关的问题,建议您查看以下的信息。
1). Lmon,lmd,lms 和 diag 进程的 trace file,来确认问题出现在 DRM 的哪一步和 lms,lmon,lmd 进程的状态。
2). AWR 和 ASH report,确认那些等待事件持续了很长时间,以及 lmon,lms 和 lmd 的状态。
3). 参照 note 1492990.1 获取 DMR 诊断脚本输出。脚本见文末附录。

5、DRM 的利弊

c93a317390b145b48f6a1e1fd9de1d15.png

  • DRM  freeze 会导致资源短暂的丌可用

  • DRM  freeze 可能导致系统 hang 住

  • Read mostly/reader  bypass  等特性带来各种 bug,可以说DRM就是 oracle 的一个鸡肋。

6、DRM 应用场景

DRM 是一把双刃剑,在一般情况下,仁者见仁智者见智,我们都是需要将其关闭的。在 Oracle 11g 及 19c 的最佳实践下也是需要将其关闭的。如果你的应用分节点分业务没有使用 scanip 单独连接的,那么最好使用 DRM 特性。

0826582c11f068e7a15c7773bf14e3d1.png

7、DRM 应用案例

在春节前的一段时间内,我司一套跨机房的 11g 的 4 节点 RAC,由于业务高峰和数据量的增加导致 DRM 问题和 GC 问题不断出现。双中心存储双活的扩展 RAC,本身也就是原先架构的问题,私网通信又是千兆网,在初期数据量小的情况下这种架构是没有问题的,但随着业务的增长及数据量的增加,弊端慢慢凸显出来了。3T 左右的数据量在 96c 256g 的物理机的配置下,平常时期是没问题的可到了业务高峰就显得那么心有余力不足了。数据库整体情况良好,无太大问题压力也很小,DRM 问题和 GC 问题不断出现只是会影响个别敏感的业务。那么该如何解决呢?数据库没有特别的个性化参数设置,此时想要调整参数必须要重启数据库,是没有时间窗口的,那么该怎么办呢?临时解决办法就是监控 GC 相关等待事件,出现问题及时手动解决,然后等待凌晨时间先关闭另一中心的两节点数据库,使其业务全部连到另一中心。下图是一次出问题时的 ASH 报告。

8486e4e1bc110d815aa0ceb168021f06.png
d885f821e4dc494de08b4a5192501f7a.png

8、关闭/禁止 DRM

怎么样来关闭/禁止DRM呢?很多 MOS 文档提到的方法是设置 2 个隐含参数:

_gc_affinity_time=0  
    _gc_undo_affinity=FALSE

不幸的是,这 2 个参数是静态参数,也就是说必须要重启实例才能生效。

实际上在 10g 的库中可以设置另外 2 个动态的隐含参数,来达到这个目的。按下面的值设置这 2 个参数之后,不能完全算是禁止/关闭了 DRM,而是从”事实上“关闭了 DRM。

_gc_affinity_limit=1000000   
    _gc_affinity_minimum=10485760
可以通过如下三个主要视图来查询 DRM 的相关统计信息:
X$KJDRMREQ:Dynamic Remastering Requests
X$KJDRMAFNSTATS:File Remastering Statistics
X$KJDRMHVSTATS:Hash Value Statistics

10gR2 以及以下版本,可使用上面方法关闭/禁用 DRM

在 11gR1 以及以上版本中

--查看 DRM 参数值
set line 456
col VALUE for a30
col NAME for a30
col DESCRIB for a60
SELECT x.ksppinm  as name,
       y.ksppstvl as value,
       y.ksppstdf as isdefault,
       x.ksppdesc describ
  FROM SYS.x$ksppi x, SYS.x$ksppcv y
 WHERE x.inst_id = USERENV('Instance')
   AND y.inst_id = USERENV('Instance')
   AND x.indx = y.indx
   AND x.ksppinm in ('_gc_policy_time', '_gc_undo_affinity');


alter system set "_gc_policy_time"=0 sid='*' scope=spfile;
alter system set "_gc_undo_affinity"=false sid='*' scope=spfile;


或 
可关闭 DRM 的局部特性(这个很重要):
alter system set "_gc_read_mostly_locking"=false scope=spfile;  
alter system set "_gc_bypass_readers"=false scope=spfile; 


关闭所有实例,然后重启实例。

9、验证 DRM 是否关闭

SQL> set pages 456 
SQL> select* from  v$policy_history where policy_event = 'initiate_affinity';


   INST_ID POLICY_EVENT         DATA_OBJECT_ID TARGET_INSTANCE_NUMBER EVENT_DATE
---------- -------------------- -------------- ---------------------- --------------------
         1 initiate_affinity            275741                      1 08/29/2022 10:39:42
         1 initiate_affinity            275863                      3 08/29/2022 10:39:42
         1 initiate_affinity            223669                      3 08/29/2022 10:39:42
         1 initiate_affinity            147903                      3 08/29/2022 11:09:44
         1 initiate_affinity            302265                      1 08/29/2022 19:00:31
         1 initiate_affinity            171487                      3 08/29/2022 20:20:39
         1 initiate_affinity            135593                      4 08/30/2022 00:31:02
         1 initiate_affinity            135439                      1 08/30/2022 01:01:04
         1 initiate_affinity            295730                      4 08/30/2022 01:01:04


10、参考链接

DRM 原理及案例探讨 https://max.book118.com/html/2016/0108/32895884.shtm
DRM 原理 https://blogs.oracle.com/database4cn/drm
深入解析 oracle 中的 DRM 原理及案例分享 https://www.modb.pro/doc/71782
Oracle RAC Cache Fusion 系列十七:Oracle RAC DRM https://www.modb.pro/db/138842
故障诊断:DRM 导致 Oracle RAC 节点 Hang 住 https://www.modb.pro/db/1394
Oracle DRM https://blog.csdn.net/wanbin6470398/article/details/86604924
DRM 阻碍了 DDL 操作问题分析 https://www.modb.pro/doc/60167

469ad4f58f73c363e34ef44fab4a6ff7.png

附录 DRMDIAG.SQL

-- NAME: DRMDIAG.SQL
-- ------------------------------------------------------------------------
-- AUTHOR: Oracle Support Services
-- ------------------------------------------------------------------------
-- PURPOSE:
-- This script is intended to provide a user friendly guide to troubleshoot
-- drm (dynamic resource remastering) waits. The script will create a file
-- called drmdiag_<timestamp>.out in your local directory.
set echo off
set feedback off
column timecol new_value timestamp
column spool_extension new_value suffix
select to_char(sysdate,'Mondd_hh24mi') timecol,
'.out' spool_extension from sys.dual;
column output new_value dbname
select value || '_' output
from v$parameter where name = 'db_name';
spool drmdiag_&&dbname&&timestamp&&suffix
set trim on
set trims on
set lines 140
set pages 100
set verify off
set feedback on


PROMPT DRMDIAG DATA FOR &&dbname&&timestamp
PROMPT Important paramenters:
PROMPT
PROMPT _gc_policy_minimum (default is 1500). Increasing this would cause DRMs to happen less frequently.
PROMPT Use the "OBJECT_POLICY_STATISTICS" section later in this report to see how active various objects are.
PROMPT
PROMPT _gc_policy_time (default to 10 (minutes)). Amount of time to evaluate policy stats. Use the
PROMPT "OBJECT_POLICY_STATISTICS" section later in this report to see how active various objects are for the
PROMPT _gc_policy_time. Usually not necessary to change this parameter.
PROMPT
PROMPT _gc_read_mostly_locking (default is TRUE). Setting this to FALSE would disable read mostly related DRMs.
PROMPT
PROMPT gcs_server_processes (default is derived from CPU count/4). May need to increase this above the
PROMPT default to add LMS processes to complte the work during a DRM but the default is usually adequate.
PROMPT
PROMPT _gc_element_percent (default is 110). May need to apply the fix for bug 14791477 and increase this to
PROMPT 140 if running out of lock elements. Usually not necessary to change this parameter.
PROMPT
PROMPT GC Related parameters set in this instance:
show parameter gc
PROMPT
PROMPT CPU count on this instance:
show parameter cpu_count


PROMPT
PROMPT SGA INFO FOR &&dbname&&timestamp
PROMPT
PROMPT Larger buffer caches (above 100 gig) may increase the cost of DRMs significantly.
set lines 120
set pages 100
column component format a40 tru
column current_size format 99999999999999999
column min_size format 99999999999999999
column max_size format 99999999999999999
column user_specified_size format 99999999999999999
select component, current_size, min_size, max_size, user_specified_size
from v$sga_dynamic_components
where current_size > 0;


PROMPT
PROMPT ASH THRESHOLD...
PROMPT
PROMPT This will be the threshold in milliseconds for total drm freeze
PROMPT times. This will be used for the next queries to look for the worst
PROMPT 'drm freeze' minutes. Any minutes that have an average log file
PROMPT sync time greater than the threshold will be analyzed further.
column threshold_in_ms new_value threshold format 999999999.999
select decode(min(threshold_in_ms),null,0,min(threshold_in_ms)) threshold_in_ms
from (select inst_id, to_char(sample_time,'Mondd_hh24mi') minute,
sum(time_waited)/1000 threshold_in_ms
from gv$active_session_history
where event like '%drm freeze%'
group by inst_id,to_char(sample_time,'Mondd_hh24mi')
order by 3 desc)
where rownum <= 10;


PROMPT
PROMPT ASH WORST MINUTES FOR DRM FREEZE WAITS:
PROMPT
PROMPT APPROACH: These are the minutes where the avg drm freeze time
PROMPT was the highest (in milliseconds).
column event format a30 tru
column program format a35 tru
column total_wait_time format 999999999999.999
column avg_time_waited format 999999999999.999
select to_char(sample_time,'Mondd_hh24mi') minute, inst_id, event,
sum(time_waited)/1000 TOTAL_WAIT_TIME , count(*) WAITS,
avg(time_waited)/1000 AVG_TIME_WAITED
from gv$active_session_history
where event like '%drm freeze%'
group by to_char(sample_time,'Mondd_hh24mi'), inst_id, event
having sum(time_waited)/1000 > &&threshold
order by 1,2;


PROMPT
PROMPT ASH DRM BACKGROUND PROCESS WAITS DURING WORST MINUTES:
PROMPT
PROMPT APPROACH: What are LMS and RS/RMV doing when 'drm freeze' waits
PROMPT are happening? LMD and LMON info may also be relevant
column inst format 999
column minute format a12 tru
column event format a50 tru
column program format a55 wra
select to_char(sample_time,'Mondd_hh24mi') minute, inst_id inst,
sum(time_waited)/1000 TOTAL_WAIT_TIME , count(*) WAITS,
avg(time_waited)/1000 AVG_TIME_WAITED,
program, event
from gv$active_session_history
where to_char(sample_time,'Mondd_hh24mi') in (select to_char(sample_time,'Mondd_hh24mi')
from gv$active_session_history
where event like '%drm freeze%'
group by to_char(sample_time,'Mondd_hh24mi'), inst_id
having sum(time_waited)/1000 > &&threshold and sum(time_waited)/1000 > 0.5)
and (program like '%LMS%' or program like '%RS0%' or program like '%RMV%'
or program like '%LMD%' or program like '%LMON%' or event like '%drm freeze%')
group by to_char(sample_time,'Mondd_hh24mi'), inst_id, program, event
order by 1,2,3,5 desc, 4;


PROMPT
PROMPT POLICY HISTORY INFO:
PROMPT See if you can correlate policy history events with minutes of high
PROMPT wait time.
select * from gv$policy_history
order by event_date;
PROMPT
PROMPT DYNAMIC_REMASTER_STATS
PROMPT This shows where time is spent during DRM operations.
set heading off
set lines 60
select 'Instance: '||inst_id inst, 'Remaster Ops: '||remaster_ops rops,
'Remaster Time: '||remaster_time rtime, 'Remastered Objects: '||remastered_objects robjs,
'Quiesce Time: '||quiesce_time qtime, 'Freeze Time: '||freeze_time ftime,
'Cleanup Time: '||cleanup_time ctime, 'Replay Time: '||replay_time rptime,
'Fixwrite Time: '||fixwrite_time fwtime, 'Sync Time: '||sync_time stime,
'Resources Cleaned: '||resources_cleaned rclean,
'Replayed Locks Sent: '||replayed_locks_sent rlockss,
'Replayed Locks Received: '||replayed_locks_received rlocksr,
'Current Objects: '||current_objects
from gv$dynamic_remaster_stats
order by 1;
set lines 120
set heading on


PROMPT
PROMPT OBJECT_POLICY_STATISTICS:
PROMPT The sum of the last 3 columns (sopens,xopens,xfers) decides whether the object
PROMPT will be considered for DRM (_gc_policy_minimum). The duration of the stats
PROMPT are controlled by _gc_policy_time (default is 10 minutes).
select object,node,sopens,xopens,xfers from x$object_policy_statistics;


PROMPT
PROMPT ACTIVE OBJECTS (OBJECT_POLICY_STATISTICS)
PROMPT These are the objects that are above the default _gc_policy_minimum (1500).
select object, node, sopens+xopens+xfers activity
from x$object_policy_statistics
where sopens+xopens+xfers > 1500
order by 3 desc;


PROMPT LWM FOR LE FREELIST
PROMPT This number should never get near zero, if it does consider the fix for bug 14791477
PROMPT and/or increasing _gc_element_percent.
select sum(lwm) from x$kclfx;


PROMPT
PROMPT GCSPFMASTER INFO WITH OBJECT NAMES
column objname format a120 tru
select o.name || ' - '|| o.subname objname, o.type#, h.*
from v$gcspfmaster_info h, obj$ o where h.data_object_id=o.dataobj#
order by data_object_id;


PROMPT
PROMPT ASH DETAILS FOR WORST MINUTES:
PROMPT
PROMPT APPROACH: If you cannot determine the problem from the data
PROMPT above, you may need to look at the details of what each session
PROMPT is doing during each 'bad' snap. Most likely you will want to
PROMPT note the times of the high drm freeze waits, look at what
PROMPT LMS, RS, RMV, LMD0, LMON is doing at those times, and go from there...
set lines 140
column program format a45 wra
column sample_time format a25 tru
column event format a30 tru
column time_waited format 999999.999
column p1 format a40 tru
column p2 format a40 tru
column p3 format a40 tru
select sample_time, inst_id inst, session_id, program, event, time_waited/1000 TIME_WAITED,
p1text||': '||p1 p1,p2text||': '||p2 p2,p3text||': '||p3 p3
from gv$active_session_history
where to_char(sample_time,'Mondd_hh24mi') in (select
to_char(sample_time,'Mondd_hh24mi')
from gv$active_session_history
where event like '%drm freeze%'
group by to_char(sample_time,'Mondd_hh24mi'), inst_id
having sum(time_waited)/1000 > &&threshold)
and time_waited > 0.5
order by 1,2,3,4,5;


spool off


PROMPT
PROMPT OUTPUT FILE IS: drmdiag_&&dbname&&timestamp&&suffix
PROMPT

全文完,希望可以帮到正在阅读的你,如果觉得此文对你有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~

欢迎关注我的公众号【JiekeXu DBA之路】,第一时间一起学习新知识!

————————————————————————————
公众号:JiekeXu DBA之路
CSDN :https://blog.csdn.net/JiekeXu
墨天轮:https://www.modb.pro/u/4347
腾讯云:https://cloud.tencent.com/developer/user/5645107
————————————————————————————

fcda2cfba45a34b4cb620c70a3fd0b55.gif

Oracle 表碎片检查及整理方案

OGG|Oracle GoldenGate 基础

2022 年公众号历史文章合集整理

2021 年公众号历史文章合集整理

2020 年公众号历史文章合集整理

Oracle 19c RAC 遇到的几个问题

OGG|Oracle 数据迁移后比对一致性

利用 OGG 迁移 Oracle11g 到 19C

OGG|Oracle GoldenGate 微服务架构

Oracle 查询表空间使用率超慢问题一则

国产数据库|TiDB 5.4 单机快速安装初体验

Oracle ADG 备库停启维护流程及增量恢复

Linux 环境搭建 MySQL8.0.28 主从同步环境
bcedefaf793715b31756da6774d75f7e.png

猜你喜欢

转载自blog.csdn.net/JiekeXu/article/details/128825752