zoukankan      html  css  js  c++  java
  • 演示共享池中的 Latch 争用

    本文内容

    • Latch 和等待
    • 共享池中的 Latch 争用

    Latch 和等待


        假设,一个数据块正在被一个会话从磁盘中读如到内存中,请注意,是正在读取中,此时,如果另外一个会话也正需要这个数据块,他该怎么办?

        此时,丈等待这个数据块被读取到内存中,这样就可以只有一个数据块在内存中,不会导致数据的不一致性。那么,正在读取数据块的会话如何能阻止别的会话继续读取这个数据块呢?方法是它需要获得一种像锁一样的资源,以便阻止其他的会话来做相同的事情,这种资源就叫 Latch。Latch 是 Oracle 为了保护内存结构而产生。

        Latch 不会造成阻塞,只会导致等待。导致 Latch 争用而等待的原因很多,内存中很多资源都可能存在争用。最常见的两类 Latch 争用:

    • 共享池中的 Latch 争用
    • 数据缓冲池中的 Latch 争用

    共享池中的 Latch 争用

    创建测试环境

        用 sys 用户登录,查看 Latch 争用情况:
    SQL> select * from v$latchname where name like 'library cache%';
     
        LATCH# NAME                                                     HASH
    ---------- -------------------------------------------------- ----------
           278 library cache load lock                            2952162927
     
    SQL>

        在分析系统性能是,如果看到 library cache 这样的 Latch 争用,就可以断定是共享池中出现了问题,这基本上是有 SQL 语句导致的,比如没有绑定变量或一些存储过程被反复分析。

        下面是来自 asktom.oracle.com 上给出的一个在有绑定变量和无绑定变量的情况下,Latch 资源争用的对比测试。该测试被很多 Oracle 书籍引用。测试让一条 SQL 语句执行1万次,然后给出各自的执行过程中产生的资源使用情况。

        用 sys 用户新建用户 test 并授权。

    SQL> create user test identified by test default tablespace users;
     
    用户已创建。
     
    SQL> grant dba to test;
     
    授权成功。
     
    SQL> grant select on sys.v_$statname to test;
     
    授权成功。
     
    SQL> grant select on sys.v_$mystat to test;
     
    授权成功。
     
    SQL> grant select on sys.v_$latch to test;
     
    授权成功。
     
    SQL> grant select on sys.v_$timer to test;
     
    授权成功。
     
    SQL>
     
    已新建用户登录。

        用 test 用户登录,执行如下操作:

    SQL> conn test/test
    已连接。
    SQL> CREATE GLOBAL TEMPORARY TABLE run_stats
      2  (
      3     runid   VARCHAR2 (15),
      4     name    VARCHAR2 (80),
      5     VALUE   INT
      6  )
      7  ON COMMIT PRESERVE ROWS;
     
    表已创建。
     
    SQL> CREATE OR REPLACE VIEW stats
      2  AS
      3     SELECT 'STAT...' || a.name name, b.VALUE
      4       FROM SYS.v_$statname a, SYS.v_$mystat b
      5      WHERE a.statistic# = b.statistic#
      6     UNION ALL
      7     SELECT 'LATCH.' || name, gets FROM SYS.v_$latch
      8     UNION ALL
      9     SELECT 'STAT...Elapsed Time', hsecs FROM SYS.v_$timer;
     
    视图已创建。
     
    SQL> CREATE OR REPLACE PACKAGE runstats_pkg
      2  AS
      3     PROCEDURE rs_start;
      4
      5     PROCEDURE rs_middle;
      6
      7     PROCEDURE rs_stop (p_difference_threshold IN NUMBER DEFAULT 0);
      8  END;
      9  /
     
    程序包已创建。
     
    SQL> CREATE OR REPLACE PACKAGE BODY runstats_pkg
      2  AS
      3     g_start   NUMBER;
      4     g_run1    NUMBER;
      5     g_run2    NUMBER;
      6
      7     PROCEDURE rs_start
      8     IS
      9     BEGIN
     10        DELETE FROM run_stats;
     11
     12        INSERT INTO run_stats
     13           SELECT 'before', stats.* FROM stats;
     14
     15        g_start := DBMS_UTILITY.get_cpu_time;
     16     END;
     17
     18     PROCEDURE rs_middle
     19     IS
     20     BEGIN
     21        g_run1 := (DBMS_UTILITY.get_cpu_time - g_start);
     22
     23        INSERT INTO run_stats
     24           SELECT 'after 1', stats.* FROM stats;
     25
     26        g_start := DBMS_UTILITY.get_cpu_time;
     27     END;
     28
     29     PROCEDURE rs_stop (p_difference_threshold IN NUMBER DEFAULT 0)
     30     IS
     31     BEGIN
     32        g_run2 := (DBMS_UTILITY.get_cpu_time - g_start);
     33
     34        DBMS_OUTPUT.put_line ('Run1 ran in ' || g_run1 || ' cpu hsecs');
     35        DBMS_OUTPUT.put_line ('Run2 ran in ' || g_run2 || ' cpu hsecs');
     36
     37        IF (g_run2 <> 0)
     38        THEN
     39           DBMS_OUTPUT.put_line (
     40                 'run 1 ran in '
     41              || ROUND (g_run1 / g_run2 * 100, 2)
     42              || '% of the time');
     43        END IF;
     44
     45        DBMS_OUTPUT.put_line (CHR (9));
     46
     47        INSERT INTO run_stats
     48           SELECT 'after 2', stats.* FROM stats;
     49
     50        DBMS_OUTPUT.put_line (
     51              RPAD ('Name', 30)
     52           || LPAD ('Run1', 12)
     53           || LPAD ('Run2', 12)
     54           || LPAD ('Diff', 12));
     55
     56        FOR x
     57           IN (  SELECT    RPAD (a.name, 30)
     58                        || TO_CHAR (b.VALUE - a.VALUE, '999,999,999')
     59                        || TO_CHAR (c.VALUE - b.VALUE, '999,999,999')
     60                        || TO_CHAR (
     61                              ( (c.VALUE - b.VALUE) - (b.VALUE - a.VALUE)),
     62                              '999,999,999')
     63                           data
     64                   FROM run_stats a, run_stats b, run_stats c
     65                  WHERE     a.name = b.name
     66                        AND b.name = c.name
     67                        AND a.runid = 'before'
     68                        AND b.runid = 'after 1'
     69                        AND c.runid = 'after 2'
     70                        AND ABS ( (c.VALUE - b.VALUE) - (b.VALUE - a.VALUE))
    >
     71                               p_difference_threshold
     72               ORDER BY ABS ( (c.VALUE - b.VALUE) - (b.VALUE - a.VALUE)))
     73        LOOP
     74           DBMS_OUTPUT.put_line (x.data);
     75        END LOOP;
     76
     77        DBMS_OUTPUT.put_line (CHR (9));
     78        DBMS_OUTPUT.put_line (
     79           'Run1 latches total versus runs -- difference and pct');
     80        DBMS_OUTPUT.put_line (
     81              LPAD ('Run1', 12)
     82           || LPAD ('Run2', 12)
     83           || LPAD ('Diff', 12)
     84           || LPAD ('Pct', 10));
     85
     86        FOR x
     87           IN (SELECT    TO_CHAR (run1, '999,999,999')
     88                      || TO_CHAR (run2, '999,999,999')
     89                      || TO_CHAR (diff, '999,999,999')
     90                      || TO_CHAR (
     91                            ROUND (
     92                                 run1
     93                               / DECODE (run2, 0, TO_NUMBER (0), run2)
     94                               * 100,
     95                               2),
     96                            '99,999.99')
     97                      || '%'
     98                         data
     99                 FROM (SELECT SUM (b.VALUE - a.VALUE) run1,
    100                              SUM (c.VALUE - b.VALUE) run2,
    101                              SUM ( (c.VALUE - b.VALUE) - (b.VALUE - a.VALUE)
    )
    102                                 diff
    103                         FROM run_stats a, run_stats b, run_stats c
    104                        WHERE     a.name = b.name
    105                              AND b.name = c.name
    106                              AND a.runid = 'before'
    107                              AND b.runid = 'after 1'
    108                              AND c.runid = 'after 2'
    109                              AND a.name LIKE 'LATCH%'))
    110        LOOP
    111           DBMS_OUTPUT.put_line (x.data);
    112        END LOOP;
    113     END;
    114  END;
    115  /
     
    程序包体已创建。
     
    SQL>
          上面操作创建了一个测试环境,包括创建用户、相关表,以及一个捕获 SQL 执行中的统计数据的存储过程。
    测试对比

        创建一个表 t。

    SQL> CREATE TABLE t (x INT);
     
    表已创建。
     
    SQL>

        创建不使用变量绑定方式执行 SQL 10000 的存储过程 p1:

    SQL> CREATE OR REPLACE PROCEDURE p1
      2  AS
      3     l_cnt   NUMBER;
      4  BEGIN
      5     FOR i IN 1 .. 10000
      6     LOOP
      7        EXECUTE IMMEDIATE 'select count(*) from t where x=' || i INTO l_cnt;
      8     END LOOP;
      9  END;
     10  /
     
    过程已创建。
     
    SQL>

        创建使用变量绑定方式执行 SQL 10000 的存储过程 p2:

    SQL> CREATE OR REPLACE PROCEDURE p2
      2  AS
      3     l_cnt   NUMBER;
      4  BEGIN
      5     FOR i IN 1 .. 10000
      6     LOOP
      7        SELECT COUNT(*)
      8          INTO l_cnt
      9          FROM t
     10         WHERE x = i;
     11     END LOOP;
     12  END;
     13  /
     
    过程已创建。
     
    SQL>
    开始测试

    SQL> exec runstats_pkg.rs_start
     
    PL/SQL 过程已成功完成。
     
    SQL> exec p1
     
    PL/SQL 过程已成功完成。
     
    SQL> exec runstats_pkg.rs_middle
     
    PL/SQL 过程已成功完成。
     
    SQL> exec p2
     
    PL/SQL 过程已成功完成。
     
    SQL> exec runstats_pkg.rs_stop(1000)
     
    PL/SQL 过程已成功完成。
     
    SQL> set serveroutput on
    SQL> exec runstats_pkg.rs_stop(1000)
    Run1 ran in 379 cpu hsecs
    Run2 ran in 26 cpu hsecs
    run 1 ran in 1457.69% of the time
     
    Name                                  Run1        Run2        Diff
    LATCH.channel operations paren       1,622         516      -1,106
    STAT...bytes sent via SQL*Net          279       1,443       1,164
    LATCH.JS queue state obj latch       1,770         540      -1,230
    LATCH.channel operations paren       1,622         245      -1,377
    LATCH.JS queue state obj latch       1,770         270      -1,500
    LATCH.checkpoint queue latch         2,323         782      -1,541
    LATCH.messages                       2,642       1,005      -1,637
    LATCH.checkpoint queue latch         2,323         314      -2,009
    LATCH.messages                       2,642         380      -2,262
    STAT...undo change vector size       2,736       5,376       2,640
    STAT...redo size                     3,704       7,252       3,548
    LATCH.SQL memory manager worka       6,784       2,109      -4,675
    LATCH.SQL memory manager worka       6,784       1,018      -5,766
    STAT...physical read bytes               0       8,192       8,192
    STAT...physical read total byt           0       8,192       8,192
    LATCH.transaction allocation        14,349       4,784      -9,565
    STAT...session logical reads        40,074      30,488      -9,586
    STAT...consistent gets              40,020      30,422      -9,598
    STAT...consistent gets from ca      40,020      30,422      -9,598
    STAT...consistent gets from ca      40,018      30,333      -9,685
    STAT...calls to get snapshot s      50,009      40,092      -9,917
    LATCH.MinActiveScn Latch            10,096         157      -9,939
    STAT...parse count (total)          10,009          29      -9,980
    STAT...parse count (hard)           10,003          13      -9,990
    STAT...enqueue releases             10,010          18      -9,992
    STAT...enqueue requests             10,011          18      -9,993
    STAT...consistent gets from ca      40,020      30,022      -9,998
    STAT...consistent gets              40,020      30,022      -9,998
    STAT...parse count (hard)           10,003           4      -9,999
    STAT...session cursor cache hi           4      10,004      10,000
    STAT...consistent gets from ca      40,018      30,018     -10,000
    STAT...parse count (total)          10,009           9     -10,000
    STAT...calls to get snapshot s      50,009      40,008     -10,001
    STAT...enqueue releases             10,010           6     -10,004
    STAT...enqueue requests             10,011           6     -10,005
    STAT...session logical reads        40,074      30,054     -10,020
    STAT...session cursor cache hi           4      10,031      10,027
    LATCH.MinActiveScn Latch            10,096           4     -10,092
    LATCH.transaction allocation        14,349       2,391     -11,958
    LATCH.cache buffers chains          48,608      34,131     -14,477
    STAT...session uga memory           16,424           0     -16,424
    STAT...sorts (rows)                      0      17,422      17,422
    LATCH.cache buffers chains          48,608      30,643     -17,965
    STAT...session uga memory max       13,600      32,072      18,472
    LATCH.kks stats                     20,013          28     -19,985
    LATCH.kks stats                     20,013           9     -20,004
    STAT...Elapsed Time                 29,521       9,331     -20,190
    LATCH.enqueue hash chains           24,596       1,966     -22,630
    LATCH.enqueues                      24,106       1,392     -22,714
    LATCH.enqueues                      24,106         634     -23,472
    LATCH.enqueue hash chains           24,596         684     -23,912
    STAT...Elapsed Time                 29,521       4,567     -24,954
    STAT...recursive calls              40,064      10,361     -29,703
    STAT...recursive calls              40,064      10,044     -30,020
    STAT...table scan rows gotten            0      34,776      34,776
    LATCH.DML lock allocation           63,719      21,430     -42,289
    LATCH.DML lock allocation           63,719      10,597     -53,122
    LATCH.shared pool simulator         56,264       1,025     -55,239
    LATCH.shared pool simulator         56,264         222     -56,042
    STAT...session pga memory         -171,272     -65,536     105,736
    STAT...session uga memory max       13,600     157,536     143,936
    STAT...session pga memory         -171,272           0     171,272
    LATCH.row cache objects            182,579       1,796    -180,783
    LATCH.row cache objects            182,579         384    -182,195
    LATCH.shared pool                  334,118      11,762    -322,356
    LATCH.shared pool                  334,118      10,499    -323,619
    STAT...session pga memory max   -1,490,300           0   1,490,300
    STAT...session pga memory max   -1,490,300   2,293,760   3,784,060
     
    Run1 latches total versus runs -- difference and pct
    Run1        Run2        Diff       Pct
    1,603,990     147,130  -1,456,860  1,090.19%
     
    PL/SQL 过程已成功完成。
     
    SQL>

        性能采集包 runstats_pkg 分别在测试开始、存储过程 p1 运行结束、存储过程 p2运行结束,这3个时间点采集性能数据,最后在报告中给出了2个存储过程各自的 Latch资源使用情况以及对比情况。

        从这个结果中可以清楚地看到不绑定变量的 Latch 争用是非常严重的,注意输出结果中几个关于 Latch 列 的 Latch 在数量的差异,可以看到,绑定变量要比不绑定,Latch 争用小得多。

    下载 runstats.rar

  • 相关阅读:
    C#转义字符,以及@的作用
    建立数据库链接 create database link以及synonym
    Oracle11g密码区分大小写导致database link无法连接
    ES5:深入解析如何js定义类或对象。
    jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
    浅析JavaScript访问对象属性和方法及区别
    Angular ui-router的常用配置参数详解
    Angular 通过constant(name,value),value(name,value)创建服务
    Angular ocLazyLoad 与ui-router的配合使用
    AngularJs指令配置参数scope详解
  • 原文地址:https://www.cnblogs.com/liuning8023/p/2983512.html
Copyright © 2011-2022 走看看