科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



ZDNet>软件频道>数据库-zhiding>PL/SQL学习之oracle排序系列二

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

  上一期讲了oracle在什么情况下需要排序,这次我们把注意力集中到与排序相关的几个内存组件      PGA:      The Process Global Area,它是属于私有内存段,段内的内容只对本进程可见,这不同于sga的共享内存段。

来源:中国IT实验室 2007年09月30日

关键字:ORACLE 数据库 SQL


  上一期讲了oracle在什么情况下需要排序,这次我们把注意力集中到与排序相关的几个内存组件
  
  PGA:
  
  The Process Global Area,它是属于私有内存段,段内的内容只对本进程可见,这不同于sga的共享内存段。
  
  pga的内存结构不需要latch来保护,因为不会有其他进程同时访问。PGA包括两个部分,fixed pga,variable pga。
  
  fixed pga保存一些数据结构和指向variable pga的指针。PGA也是通过freelist和bucket来分配和管理。
  
  UGA:
  
  User Global Area,它包含以下一些信息
  
  The persistent and runtime areas for open cursors
  State information for packages, in particular package variables
  Java session state
  The roles that are enabled
  Any trace events that are enabled
  The NLS parameters that are in effect
  Any database links that are open
  The session's mandatory access control (MAC) label for Trusted Oracle
  
  和PGA一样,它也分为fixed,variable两个部分,同样通过freelist和bucket分配和管理内存。
  
  CGA:
  
  Call Global Area,跟PGA不一样,CGA只是短暂存在的,它只存在于每一次调用周期,当
  
  Parse an SQL statement
  Execute an SQL statement
  Fetch the outputs of a SELECT statement
  
  的时候它会被使用到
  
  在分析语句的时候产生的递规调用将会使用到CGA,包括用于检查语义,生成执行计划,PL/SQL中的递规调用也会用到它,DML的触发器递规
  
  调用同样会需要它。Java Call Memory也是在CGA中,这也是ORACLE内存管理中唯一一个用到垃圾收集(garbage collection)的内存区域。
  
  关于PGA,UGA,CGA的详细解释请参考Steve Adamas的<<oracle8i internal services for waits, latches, locks>>
  
  sort_area_size:
  
  排序空间的最大限制,在完成排序阶段后,oracle将释放内存并保留sort_area_retained_size用于fetch阶段,当最后一条记录被fetch回客户端后,oracle将会释放sort_area_retained_size。
  
  sort_area_retained_size:
  
  在UGA中分配的排序空间,当oracle发生排序时,先会从UGA中分配内存直到达到sort_area_retained_size的限制,然后会继续在PGA中分配内存一直到sort_area_size限制,如上面所说的,sort_area_retained_size将会在fetch阶段被保留,在fetch完成后释放给OS或PGA(区别在于是否UGA是PGA的subheap)
  
  在9iR2版本以前,UGA,CGA一直是PGA的subheap,当它们被释放后将会释放给PGA而不是释放给OS,这是由于PGA的内存分配是通过malloc,brk来实现的,但是从9iR2版本开始,我们有了选择,_use_realfree_heap参数给我们机会去改变PGA内存的分配方式,当_use_realfree_heap为true时,PGA的内存分配将会通过mmap来实现,这样当调用munmap的时候将不必将内存返回给进程而直接返回给OS.下面我们来验证一下
  
  alter system set "_use_realfree_heap"=true;
  ALTER SESSION SET EVENTS
  'immediate trace name heapdump level 1';
  
  HEAP DUMP heap name="pga heap" desc=0xc6a6400
  extent sz=0x206c alt=92 het=32767 rec=0 flg=2 opc=2
  parent=(nil) owner=(nil) nex=(nil) xsz=0xfff8
  EXTENT 0 addr=0xb72c0008
  ******************************************************
  ******************************************************
  HEAP DUMP heap name="top call heap" desc=0xc6a8c00
  extent sz=0x206c alt=100 het=32767 rec=0 flg=2 opc=2
  parent=(nil) owner=(nil) nex=(nil) xsz=0xfffc
  EXTENT 0 addr=0xb72b0004
  Chunk b72b000c sz=  32780  perm   "perm      " alo=40
  Chunk b72b8018 sz=  31672  free   "        "
  Chunk b72bfbd0 sz=   1072  recreate "callheap    " latch=(nil)
  ds c6a8300 sz=   1072 ct=    1
  Total heap size  =  65524
  ******************************************************
  ******************************************************
  HEAP DUMP heap name="top uga heap" desc=0xc6a8d20
  extent sz=0xffdc alt=100 het=32767 rec=0 flg=3 opc=3
  parent=(nil) owner=(nil) nex=(nil) xsz=0xfffc
  EXTENT 0 addr=0xb72e0004
  Chunk b72e000c sz=  65524  free   "        "
  EXTENT 1 addr=0xb72d0004
  Chunk b72d000c sz=    48  free   "        "
  Chunk b72d003c sz=  65476  recreate "session heap  " latch=(nil)
  ds b72c7628 sz=  65476 ct=    1
  Total heap size  =  131048
  
  当_use_realfree_heap为true时,pga,uga,cga为独立的heap
  
  strace -p xxxx -o 1.txt
  
  mmap2(0xb7271000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7271000
  mmap2(0xb7281000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7281000
  mmap2(0xb7291000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7291000
  mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE, 7, 0xf1) = 0xb7121000
  mmap2(0xb7121000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7121000
  mmap2(0xb7131000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7131000
  mmap2(0xb7141000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7141000
  mmap2(0xb7151000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7151000
  mmap2(0xb7161000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0) = 0xb7161000
  
  同时可以看到内存分配是通过mmap来实现的
  
  alter system set "_use_realfree_heap"=false;
  
  ALTER SESSION SET EVENTS
  'immediate trace name heapdump level 1';
  
  HEAP DUMP heap name="pga heap" desc=0xc6a6400
  extent sz=0x206c alt=92 het=32767 rec=0 flg=3 opc=3
  parent=(nil) owner=(nil) nex=(nil) xsz=0x206c
  EXTENT 0 addr=0xc74a7b8
  Chunk c74a7c0 sz=   8292  free   "        "
  EXTENT 1 addr=0xc748740
  Chunk c748748 sz=   4148  free   "        "
  Chunk c74977c sz=   4144  freeable "session heap  " ds=0xc73332c
  
  当_use_realfree_heap为true时,uga,cga为pga的subheap
  
  strace -p xxxx -o 2.txt
  
  brk(0xc7fb000)             = 0xc7fb000
  brk(0xc823000)             = 0xc823000
  brk(0xc852000)             = 0xc852000
  brk(0xc881000)             = 0xc881000
  brk(0xc8b1000)             = 0xc8b1000
  brk(0xc8e0000)             = 0xc8e0000
  brk(0xc90f000)             = 0xc90f000
  brk(0xc93f000)             = 0xc93f000
  brk(0xc96e000)             = 0xc96e000
  brk(0xc99d000)             = 0xc99d000
  
  同时可以看到内存分配是通过brk来实现的
  
  我们再来看一下在_use_realfree_heap不同设置下uga,pga的内存使用情况
  
  _use_realfree_heap=true
  
  SQL 10G>select * from testsort order by 1,2,3;
  
  398608 rows selected.
  
  SQL 10G>/
  
  NAME                               MEM
  ---------------------------------------------------------------- -----------------------------------------
  session uga memory                        1.8679962158203125M
  session uga memory max                      49.53220367431640625M
  session pga memory                        4.808185577392578125M
  session pga memory max                      62.308185577392578125M
  
  SQL 10G>/
  
  NAME                               MEM
  ---------------------------------------------------------------- -----------------------------------------
  session uga memory                        49.78192901611328125M
  session uga memory max                      49.78192901611328125M
  session pga memory                        52.808185577392578125M
  session pga memory max                 

查看本文来源


  下一次我们将分享自动管理PGA
  
  set constraint,alter session set constraint,有条件的unique限制
  
  set constraint 子句是用来设置deferrable constraint的状态的,可以设置constraint的状态为immediate或deferred,具体语法请看
  http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_104a.htm#2066962
  
  它的作用域在事务级别,一旦事务结束constraint的状态恢复初始值
  
  SQL 10G>create table t
  ( x int constraint check_x check ( x > 0 ) deferrable initially immediate,
  y int constraint check_y check ( y > 0 ) deferrable initially deferred
  )
  /
  
  SQL 10G>conn test/test
  Connected.
  SQL 10G>desc user_constraints
  Name                   Null?  Type
  ----------------------------------------- -------- ----------------------------
  OWNER                   NOT NULL VARCHAR2(30)
  CONSTRAINT_NAME              NOT NULL VARCHAR2(30)
  CONSTRAINT_TYPE                  VARCHAR2(1)
  TABLE_NAME                NOT NULL VARCHAR2(30)
  SEARCH_CONDITION                  LONG
  R_OWNER                      VARCHAR2(30)
  R_CONSTRAINT_NAME                 VARCHAR2(30)
  DELETE_RULE                    VARCHAR2(9)
  STATUS                       VARCHAR2(8)
  DEFERRABLE                     VARCHAR2(14)
  DEFERRED                      VARCHAR2(9)
  VALIDATED                     VARCHAR2(13)
  GENERATED                     VARCHAR2(14)
  BAD                        VARCHAR2(3)
  RELY                        VARCHAR2(4)
  LAST_CHANGE                    DATE
  INDEX_OWNER                    VARCHAR2(30)
  INDEX_NAME                     VARCHAR2(30)
  INVALID                      VARCHAR2(7)
  VIEW_RELATED                    VARCHAR2(14
  
  查看constraint的初始值
  
  SQL 10G> select CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS,DEFERRABLE,DEFERRED from user_constraints where table_name='T';
  CONSTRAINT_NAME        C STATUS  DEFERRABLE   DEFERRED
  ------------------------------ - -------- -------------- ---------
  CHECK_X            C ENABLED DEFERRABLE   IMMEDIATE
  CHECK_Y            C ENABLED DEFERRABLE   DEFERRED
  
  由于x列的初始值为immediate,所以当发生insert的时候就直接报错了
  
  SQL 10G>insert into t values(-1,1);
  insert into t values(-1,1)
  *
  ERROR at line 1:
  ORA-02290: check constraint (TEST.CHECK_X) violated
  
  设定constraint为deferred
  
  SQL 10G>set constraints all deferred;
  Constraint set.
  SQL 10G>insert into t values(-1,1);
  1 row created.
  SQL 10G>commit;
  commit
  *
  ERROR at line 1:
  ORA-02091: transaction rolled back
  ORA-02290: check constraint (TEST.CHECK_X) violated
  
  可以看到constraint设置起作用了
  
  再次insert又报错误,因为set constraint的作用域是事务级的,已经恢复到初始设置
  
  SQL 10G>insert into t values(-1,1);
  insert into t values(-1,1)
  *
  ERROR at line 1:
  ORA-02290: check constraint (TEST.CHECK_X) violated
  
  使用alter session 来进行session级别的constraint设置
  
  SQL 10G>alter session set constraints=deferred;
  Session altered.
  SQL 10G>insert into t values(-1,1);
  1 row created.
  SQL 10G>commit;
  commit
  *
  ERROR at line 1:
  ORA-02091: transaction rolled back
  ORA-02290: check constraint (TEST.CHECK_X) violated
  
  SQL 10G>insert into t values(-1,1);
  1 row created.
  SQL 10G>commit;
  commit
  *
  ERROR at line 1:
  ORA-02091: transaction rolled back
  ORA-02290: check constraint (TEST.CHECK_X) violated
  
  可以发现在session级别内constraint的设置都保持有效
  
  下面来演示一下有条件的unique限制
  
  SQL 10G>drop table t;
  Table dropped.
  
  SQL 10G>create table t(a varchar2(10),b number);
  Table created.
  SQL 10G>create unique index uni_t
  2 on t( case when a = 'ACTIVE' then b end );
  Index created.
  
  SQL 10G>insert into t values('a',1);
  1 row created.
  
  SQL 10G>insert into t values('a',1);
  1 row created.
  
  SQL 10G>commit;
  Commit complete.
  
  SQL 10G>insert into t values('ACTIVE',1);
  1 row created.
  
  SQL 10G>insert into t values('ACTIVE',1);
  insert into t values('ACTIVE',1)
  *
  ERROR at line 1:
  ORA-00001: unique constraint (TEST.UNI_T) violated
  
  通过函数索引就实现了有条件的unique限制,不考虑性能问题的话倒是一个好的方法
  
  数据库打开情况下删除数据文件会发生什么(unix)
  
  创建测试表空间及表
  
  SQL 10G>create tablespace testearse datafile '/opt/oracle/oradata/dbtest/testearse.dbf' size 1m;
  Tablespace created.
  
  SQL 10G>create table testearse(a number) tablespace testearse;
  Table created.
  
  看看有哪些进程关联到这个数据文件
  
  SQL 10G>!
  [oracle@csdba ~]$ lsof |grep testearse
  oracle   4424 oracle  33uW   REG    8,9  1056768   852911 /opt/oracle/oradata/dbtest/testearse.dbf
  oracle  25121 oracle  15u   REG    8,9  1056768   852911 /opt/oracle/oradata/dbtest/testearse.dbf
  
  删除这个数据文件
  
  [oracle@csdba ~]$ rm /opt/oracle/oradata/dbtest/testearse.dbf
  [oracle@csdba ~]$
  
  再观看lsof的结果,发现相关的状态已经变成deleted,但是文件还是保持打开状态
  
  [oracle@csdba ~]$ lsof |grep testearse
  oracle   4424 oracle  33uW   REG    8,9  1056768   852911 /opt/oracle/oradata/dbtest/testearse.dbf (deleted)
  oracle  25121 oracle  15u   REG    8,9  1056768   852911 /opt/oracle/oradata/dbtest/testearse.dbf (deleted)
  
  oracle  4424   1 0 Sep14 ?    00:00:35 ora_dbw0_dbtest
  oracle  25121 25893 0 14:41 ?    00:00:00 oracledbtest (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
  
  SQL 10G>insert into testearse values(10);
  1 row created.
  SQL 10G>commit;
  Commit complete.
  SQL 10G>alter system checkpoint;
  System altered.
  SQL 10G>insert into testearse values(10);
  1 row created.
  SQL 10G>commit;
  SQL 10G>select * from testearse;
  A
  ----------
  10
  10
  
  SQL 10G>ALTER SESSION SET EVENTS 'immediate trace name flush_cache';
  Session altered.
  
  SQL 10G>select * from testearse;
  A
  ----------
  10
  10
  
  由于本身sqlplus的process和testearse.dbf还建立连接,所以这时仍然可以对这个表进行操作
  
  退出sqlplus,重新开启sqlplus
  
  SQL 10G>exit
  Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
  With the Partitioning and Data Mining Scoring Engine options
  
  [oracle@csdba ~]$ lsof |grep testearse
  oracle   4424 oracle  33uW   REG    8,9  1056768   852911 /opt/oracle/oradata/dbtest/testearse.dbf (deleted)
  
  这时只剩下dbwr进程和testearse.dbf还建立连接
  
  [oracle@csdba bdump]$ sqlplus "/ as sysdba"
  SQL*Plus: Release 10.2.0.1.0 - Production on Mon Oct 10 15:47:58 2005
  Copyright (c) 1982, 2005, Oracle. All

查看本文来源

推广二维码
邮件订阅

如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

重磅专题