Oracle latch

Oracle latch vs lock

	latch			lock
队列行	无队列性		队列性
时长	很短			可能很长
层面	数据库资源层		业务应用层
目的	保证资源的完整性	保证业务操作的完整性


latch在sga中,并不会存在pga中,因为sga中才会存在并发。
latch主要存在两块:

共享池
- sql解析,sql重用

数据缓冲区
-数据访问,数据写入,数据读入
-修改数据块
-数据段扩展

latch获取方式

wait方式--如果无法获取请求的latch,则
1.spin
当一个会话无法获得需求的latch时,会继续使用cpu(cpu空转),达到一个间隔时,会
在此尝试申请latch,知道达到最大重试次数。
2.sleep
当一个会话无法获取需要的latch时,会等待一段时间,达到一个间隔时,在此尝试申请latch,
如此反复,知道达到最大的重试次数。

第一种是系统可以认为立马下次可以获取到latch,而第二种则sleep一段时间后再进行获取

Nowait方式
--如果无法获取请求的latch,则
不会发生sleep或者spin
转而获取其他的可用latch


对于绑定变量,olap中没必要使用绑定变量,因为sql执行不会太多。
而oltp中,建议使用绑定变量。

data buffer中的latch争用
1.表数据块争用。
2.热块索引数据热块
3.文件头修改 --并发修改

模拟下表数据块的争用

admin@ORCL> create table latch_table1 as select * from dba_objects;

Table created.

--创建访问的存储过程
admin@ORCL> create or replace procedure p1 as
  2    l number;
  3  begin
  4    for i in 1 .. 8000 loop
  5      select count(*) into l from latch_table1 where object_type = 'TABLE';
  6    end loop;
  7    dbms_output.put_line('successfully');
  8  end;
  9  /

Procedure created.

--三个会话同时执行访问latch表

admin@ORCL> select distinct sid from v$mystat;

       SID
----------
        10

admin@ORCL> exec p1;


admin@ORCL> select distinct sid from v$mystat;

       SID
----------
       192

admin@ORCL> exec p1;


admin@ORCL> select distinct sid from v$mystat;

       SID
----------
        71

admin@ORCL> exec p1;

--捕获到PID 33在访问时遇到了latch争用的情况。
PID:持有lantch的进程。
SID:持有latch的会话。
LADDR:latch的地址
NAME:latch的名称
GETS:获得latch的次数。


admin@ORCL> select * from v$latchholder;

       PID        SID LADDR                NAME                       GETS
---------- ---------- -------------------- -------------------- ----------
        33         71 000007FF0E175D80     cache buffers chains      88877


--看在会话等待事件视图中总是有这3个会话的“latch 链表”的争用,原因当多个会话同时去访问相同数据块时,它们首先申请latch获得访问权限,
如果此时申请失败,将会产生“latch: cache buffers chains”等待事件,这是因为多个会话在争抢latch资源所致
admin@ORCL> select SID,EVENT from V$SESSION_WAIT where wait_class <> 'Idle';

       SID EVENT
---------- ----------------------------------------------------------------
        10 latch: cache buffers chains
        71 latch: cache buffers chains
       192 latch: cache buffers chains


--创建三个存储过程,测试下数据块修改导致的事件
admin@ORCL> create or replace procedure p2
  2  as
  3        l number;
  4  begin
  5        for i in 1..100
  6        loop
  7           update latch_table1 set object_type='TABLE' where object_type='TABLE';
  8        end loop;
  9        dbms_output.put_line('successfully');
 10  end;
 11  /

Procedure created.

admin@ORCL> create or replace procedure p3
  2  as
  3        l number;
  4  begin
  5        for i in 1..100
  6        loop
  7           update latch_table1 set object_type='INDEX' where object_type='INDEX';
  8        end loop;
  9        dbms_output.put_line('successfully');
 10  end;
 11  /

Procedure created.

admin@ORCL> create or replace procedure p4
  2  as
  3        l number;
  4  begin
  5        for i in 1..100
  6        loop
  7           update latch_table1 set object_type='VIEW' where object_type='VIEW';
  8        end loop;
  9        dbms_output.put_line('successfully');
 10  end;
 11  /

Procedure created.

--首先可以看出,当DML操作进行之前,访问相同的数据块导致了热块,数据块访问的争用。
我们看到DML操作不仅仅有cache buffer chains,还会产生buffer busy waits。

admin@ORCL> select * from v$latchholder;

       PID        SID LADDR                NAME                       GETS
---------- ---------- -------------------- -------------------- ----------
        31        192 000007FF0E176648     cache buffers chains       5798


admin@ORCL> select * from v$latchholder;

       PID        SID LADDR                NAME                       GETS
---------- ---------- -------------------- -------------------- ----------
        32         10 000007FF0E195158     cache buffers chains    1641739

admin@ORCL> select * from v$latchholder;

       PID        SID LADDR                NAME                       GETS
---------- ---------- -------------------- -------------------- ----------
        33         71 000007FF0E162EC8     cache buffers chains    1761049


admin@ORCL> select SID,EVENT from v$session_wait where wait_class <> 'Idle';

       SID EVENT
---------- ----------------------------------------------------------------
        10 buffer busy waits
        71 buffer busy waits
       135 SQL*Net message to client
       192 db file sequential read

--针对热块的问题,可以使用minimize records_per_block;  指定每个数据块中可存放行数减少到最小(即4行)
但这样也会导致Oracle会读取更多的数据块来完成查询。



--说明索引数据块中出现热块的场景

create table t1 (id  number , name  varchar2(200)); 

drop table t1 purge; 


insert into t1  select object_id,object_name from dba_objects;
create index t1_index on t1(id); 

execute dbms_stats.gather_table_stats('ADMIN','T1',cascade=>true);  

  

CREATE OR REPLACE PROCEDURE P10
AS
L NUMBER;
BEGIN
  FOR I IN 1..50000
    LOOP
      SELECT COUNT(*) INTO L FROM T1 WHERE ID < 10000;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('SUCESSFULLY');
END; 


admin@ORCL> select s1.sid, s2.event
  2    from v$session s1, v$session_wait s2
  3   where s1.sid = s2.sid
  4     and s1.status = 'ACTIVE'
  5     and s2.event like '%buffer%'; 

       SID EVENT
---------- ----------------------------------------------------------------
         6 latch: cache buffers chains
         8 latch: cache buffers chains
       197 latch: cache buffers chains 

 --解决办法:创建反向索引 

 

你可能感兴趣的:(oracle)