我们先看一个具体的例子
会话1,创建一个简单表,并在上面创建一个存储过程:
- 11gR1 Piner>create table test (a int);
-
- Table created.
-
- 11gR1 Piner>create or replace procedure sp_test
- 2 as
- 3 num number;
- 4 begin
- 5 select count(*) into num from test;
- 6 end;
- 7 /
-
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
同样的会话,我们插入一条记录,查看锁状态:
- 11gR1 Piner>insert into test values(1);
-
- 1 row created.
-
- 11gR1 Piner>SELECT USERENV('SID') FROM DUAL;
-
- USERENV('SID')
- --------------
- 118
-
- 11gR1 Piner>select sid,id1,id2,type,lmode,request from v$lock
- 2 where sid = 118;
-
- SID ID1 ID2 TY LMODE REQUEST
- ---------- ---------- ---------- -- ---------- ----------
- 118 99 0 AE 4 0
- 118 71091 0 TM 3 0
- 118 524292 679 TX 6 0
可以看到,这里对比以前的版本,多了一个类型为AE的锁。
然后,我们在另外一个会话做另外的操作
会话2:增加列
- SQL> alter table test add b int;
-
- Table altered.
-
- SQL> alter table test drop column b;
- alter table test drop column b
- *
- ERROR at line 1:
- ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
-
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
可以看到,列增加成功,并没有任何阻塞,但是,drop列是阻塞的。是因为add新列并不影响正在执行的dml,但是drop老列却是可能影响到正在执行的DML的。
也可以看到,增加列的过程完成以后,存储过程并不失效。这个是很好的一个特性,只要不让存储过程错误,就不会使得存储过程INVALID,减少了DDL引发的library cache pin可能导致的系统异常。
我们另外看看oracle 11g的一个ddl timeout参数,在会话2上修改此参数,并重新执行刚才的drop列的命令。
- SQL> show parameter ddl_lock_timeout;
-
- NAME_COL_PLUS_SHOW_PARAM TYPE VALUE_COL_PLUS_SHOW_PARAM
- ------------------------------ ----------- --------------------------
- ddl_lock_timeout integer 0
-
- SQL> alter system set ddl_lock_timeout = 10;
-
- System altered.
-
- SQL> set timing on
- SQL> alter table test drop column b;
- alter table test drop column b
- *
- ERROR at line 1:
- ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
-
- Elapsed: 00:00:10.00
这里的ddl_lock_timeout表示ddl会等待设置的值(单位为秒),这个是很有用的,比如在一个更新很频繁的表上面,适当的等待可以让ddl执行成功,以前dcba专门写了一个循环来模拟这个等待,现在,终于有这个参数了。
可以看到,正好等待10s左右
现在,会话1,我们提交该事务
- 11gR1 Piner>commit;
-
- Commit complete.
会话2,drop终于可以成功了
- SQL> alter table test drop column b;
-
- Table altered.
我们再查看存储过程的状态
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
整个简单测试到此完成,大家看到了几处跟以前10g不一样的地方?可以看到的是,oracle在一些细节的地方,处理的越来越好了。
如果在几年以前,谈起数据库的安全,估计没有多少人会理解其重要性。但是,现在不同了,因为更多敏感信息的泄露或篡改而导致身份窃取和财务违规的现象,让企业,特别是上市公司,不得不重视安全问题。
目前,减轻内部安全威胁的呼声越来越高,加之美国萨班法案(Sarbanes-Oxley)、美国HIPAA法案(Health Insurance Portability and Accountability Act)、日本个人信息保护法案、欧盟隐私和电子通信指令等法规和隐私保护指令的不断出台,保护数据免受未授权访问已经成为当务之急。
为了解决这个问题,oracle去年推出了Oracle Database Vault,一个从数据库层面上解决安全问题的产品。 Oracle Database Vault帮助客户保护敏感信息免遭内部威胁,并实施分责指令,要求敏感任务由多人完成。但是数据库至少是9208或者是10.2.3,在oracle 11g有进一步的加强。database vault可通过下列方法解决一些最为常见的安全问题和内部威胁:
·限制特权DBA,如sysdab以及有select any table的授权用户访问应用程序数据。
·防止应用程序 DBA 操纵数据库和访问其他应用程序。
·更好的控制何人、何时、何地可以访问应用程序。
Oracle Database Vault体现出来的三权为:
管理dba:通常是sysdba,如果安装并激活了database vault,sysdba的权限将大大减少,操作系统认证也将失效,没有alter user等等特权,不能查看由Oracle Database Vault保护起来的业务数据。举一个例子,你有一个业务用户叫HR,已经被database vault给保护起来了,你就是有再大的查看权限,如select any table,你也查看不了HR用户下的数据。所以,管理dba的作用就是启动关闭数据库,管理数据文件,管理表空间等等。
应用或者是开发dba:因为不能通过OS认证登陆数据库,所以,他们在没有sys等特权用户的密码的情况下,是不能管理数据库的。但是,他们知道应用用户的密码,如能登陆HR用户,看到HR用户下的数据。但是,每个用户也是分割的,如HR用户可以看到HR下面的数据,但是不能看到finance用户下的数据。
审计用户/管理员:这个用户可以配置database vault策略,也拥有一些alter user之类的特权命令的执行权,他们还可以查看管理dba与开发dba的一些违规操作。但是,最主要的是,他们要指定好策略,实现上面所说的,更好的控制何人、何时、何地可以访问应用程序。如,可以规定,这个数据库的某个用户数据,只能在特定的IP地址的机器上能访问;也可以规定,比如财务数据,只能从早上8点到晚上18点能接受访问,其它时间任何人都不能访问到该数据。
Oracle Database Vault是甲骨文公司安全产品系列的一个组成部分,可与Oracle标记安全(OracleLabel Security)、Oracle透明数据加密(Oracle Transparent Data Encryption)、Oracle虚拟专有数据库(Oracle Virtual Private Database)、Oracle安全备份(Oracle Secure Backup)等其他Oracle数据库安全产品一起使用,以实现更高级别的信息保护。
现在database vault遭遇到的最大的困难可能还是可靠度方面以及性能方面的问题,到底有多少人用到了这个东西,是否有bug,性能影响到底有多大等等。在性能方面,因为它会改变select语句的行为(权限),我怀疑一个策略的改变将引发众多语句的重新编译,这个情况在高可用的OLTP环境中则是比较恐怖的。
其实,数据库的安全,也仅仅是所有安全策略中的一个小部分,如果安全做的好,我们就不再仅仅是依靠dba或者是sa的人品了。
早些年,特别是Oracle版本8与版本9,Oracle图形界面做的是比较鸡肋的,不仅仅是用起来很不爽,而且极为不方便。所以,在这些版本上,使用oracle图形界面的人是少之为少。另外,因为一定的偏见,认为不用图形界面,而敲敲字符都是高手的表现,itpub曾经也出现过这样的讨论,调查有多少人能离开图形界面而工作,而且大部分的人认为,只用字符界面,如一个sqlplus就能解决所有问题,那肯定是高手。
不可否认,使用字符界面管理数据库的难度是比图形界面要大的,很多远程系统,如远程unix/linux,一般只能通过telnet或者是ssh登陆上去,这些情况下,只能使用字符界面来处理问题,所以,能通过高难度的字符界面能解决所有问题,那的确就是高手了。而且,在实际情况中,因为图形界面包装的东西太多,如果dba真的只会只用图形界面,而现在出现了一个错误,dba可能会对该错误束手无策,因为图形界面在这里不能给他提供太多的帮助。
但是,我们需要想到,如果一个公司的数据库非常多,他们的确是不需要所有的人都很精通字符界面管理,他们也招不到这么多的高手来管理数据库,专家永远只是其中一小部分,大部分的人,如果图形界面做的好,只要通过图形界面做做简单的工作就够了。这样有最明显的好处,就是成本的下降,公司对DBA的要求可能没有以前那么高,只要知道在哪里怎么点鼠标就可以了。
所以,按照Oracle的战略思想,oracle从来就没有放弃过图形界面,而且,oracle加强了图形界面的能力,如10g采用的web方式的em,在dba可以很方便的使用图形界面;如oracle把大量的内容集成到图形界面中,在字符界面你甚至找不到这些功能的操作文档,如优化模块,如一些集成功能,如database vault,等等。
oracle 11g再次对em加强,基本上通过em已经能完成了全部的字符界面能完成的数据库管理,而且,很多字符界面不支持的操作,或者是完成起来很困难的操作,现在点点鼠标就可以完成了。甚至,连一些常见错误,现在在图形界面中,都能自动处理了。那么,按照oracle的想法,以后的数据库管理,你喜欢用也好,不喜欢用也好,都去用em吧,图形界面用的好也可以培养出高手。
Oracle还不遗余力开发了集中管理模式,如OEM grid control,通过这个模块,可以通过web很方便的集中管理几十台oralce数据库,还可以是除oracle以外的数据库,甚至主机,OS等等。再想想其它公司的很多产品,如emc ecc,veritas I3,quest Central等等,都是在做基本同样的事情,看这个样子就知道,这里面的市场其实还是很大的,也证明了需求也还是瞒大的。
lob字段这里通常表示Blob,Clob与Bfiles字段,但是经常情况下,我们只讨论Blob与Clob字段,以下的Blob字段就表示Blob与Clob。Blob一般用于保存2进制的数据,如图片等,Clob一般可以用于保存文字等字符信息,与数据库的字符集有密切关系。
创建带LOB字段的完整语法为:
- Create table DemoLob ( A number, B clob )
- LOB(b)
- STORE AS lobsegname (
- TABLESPACE lobsegts
- STORAGE (lobsegment storage clause)
- [CHUNK 8K disable storage in row]
- INDEX lobindexname (
- TABLESPACE lobidxts
- STORAGE ( lobindex storage clause )
- )
- )
- TABLESPACE tables_ts
- STORAGE( tables storage clause );
其中,store as (enable storage in row|disable storage in row)表示是否允许lob数据保存在行内(与其他字段数据放在表段)。对于enable storage in row,表示允许小于4000字节的lob字段信息保存在表段,是默认值,对于大于4000字节的lob字段保存在lob段(同disable storage in row),在表段将保留36-84字节的控制信息。对于disable storage in row,Oracle将lob字段分开保存在lob段中,而仅仅在行位置保留20字节的指针。对于相当于disable storage in row的这部分(也就是单独保存在LOB段的这部分数据),UNDO仅仅是记录指针与相关lob索引改变,如果发生更新操作等DML操作,原始数据将保留在LOB段。
storage as ( CHUNK bytes )表示对于disable storage in row的这部分,最小的LOB块的大小,必须是数据库块(DB_BLOCK_SIZE)的整数倍。一个chunk最多只保留一行LOB数据,也就是说,如果你设置了32K的CHUNK,但是如果LOB字段大小只有4K,也将占用32K的空间。
storage as(cache|nocahce)表示是否允许lob段经过buffer cache并缓存。默认是nocache,表示直接读与直接写,不经过数据库的data buffer。所以,默认情况下,对于单独保存在LOB段的这部分数据,在发生物理读的时候,是直接读,如direct path read (lob)
storage as(nocache logging |nocache nologging),logging/nologging属性只对nocache方式生效,默认是logging,如果是nologging方式,对于保存在行外的log部分,在update等DML操作时将不记录redo日志。
LOB段也可以利用move来重整数据,以下的语句会将表与lob字段move到指定的表空间:
- alter table table_name move [tablespace tbs_name]
- lob(lob_field1,lob_field2) store as (tablespace new_tbs_name);
如果LOB字段在分区表中,则增加partition关键字,如
- alter table table_name move [partition partname] [tablespace tbs_name]
- lob(field) store as (tablespace new_tbs_name);
lob段的信息可以从dba/all/user_lobs中获得,并可以与其它段一样,从user_segments/user_extents中获得段与区间信息。
以前写过一篇:怎么样在业务繁忙时期正确的创建表约束,除了约束,这里也有必要介绍一下怎么在业务繁忙时期创建或者是重组索引。重新创建(create)索引的主要原因是因为新的业务的发展的需要,而重组索引往往是因为索引的偏移膨胀或者是数据删除引起的稀疏状态,也就是有些人说的“碎片”,这个情况下,我们就可以在线重组索引(rebuild online)。
当然,如果需要创建的索引或者需要重组的索引很小,创建与重组过程在几秒之内,这些都可以直接做而不需要讨论。实际情况是,业务很繁重以及表与索引都很大。这些情况下我们需要注意些什么呢?
1、创建新索引
首先,评估该索引的需要程度,如果不是特别紧急的大索引,最好在维护时间操作,还要评估该索引是否会对现有的语句造成负面影响,如导致以前的语句错误的走到这个新索引上(在日期打头的索引上,很容易出现这样的问题)。
然后,根据索引大小以及需要在上面创建的表业务是否繁忙,如果业务繁忙,尽量选择业务不繁忙的时间,系统负载不高的情况下做,避免额外的消耗,如凌晨2点-6点进行操作。创建索引之前评估索引的大小以及索引所在表空间剩余空间的大小,除此之外,还要评估临时表空间大小是否足够,用于创建索引时的排序操作。
最后,确定要创建以后,可以采用online模式创建,并且在创建的时候马上分析。
- SQL>create index index_name on table_name (field1,field2) tablespace tbs_name online [compute statistics];
创建完成以后,还要马上检查系统应用,如果发现有错误走到该索引的语句,并且有严重影响的,可能需要立即删除该索引或者约束。
- SQL>alter table table_name drop constraint constraint_name cascade;
- SQL>drop index index_name;
在一些情况下,需要改造一个索引,如添加一个字段到索引或者从索引中删除一个字段,这个时候也需要重新创建索引,但是需要严格按照如下顺序来操作
a、创建新的替代索引(如加字段或者减字段后的索引)
b、测试新的索引没有任何问题
c、删除原来的索引
2、重组索引
如果索引因为更新太频繁或者是删除数据过多,可能引起索引的数据稀疏分布,造成大量的空间浪费,并且严重影响索引的扫描速度。这样的情况下,我们需要对该索引进行空间重组。
重组之前,因为重组索引的时候,先并不删除以前的索引,同样需要确认重组以后的索引所在的表空间是否有足够的空间,以及是否有足够的临时表空间用于排序。同样,如果索引很大,而且使用比较频繁,请确认在业务不繁忙的时候操作。
- SQL>alter index index_name rebuild [tablespace tbs_index2] online [compute statistics];
3、快速创建/重组
有的时候,索引实在太大,如几十个G的索引,创建一次或者重组一次需要耗费很长的时间,如果硬件条件许可,我们可以采用一些特殊的方法来提高速度,如采用大的排序区,并行操作等等。
- SQL>alter session set sworkarea_size_policy=manaul;
- SQL>alter session set sort_area_size=1073741824;
- SQL>alter session set sort_area_retained_size=1073741824;
- SQL>alter session set db_file_multiblock_read_count=128;
- --parallel 2
- SQL>alter index index_name rebuild online parallel 2 compute statistics;
然后,特别需要注意的是,在并行创建或者重组完成以后,一定要取消索引的并行度,否则,在OLTP环境中,可能会因为意外的使用并行而出现严重性能问题。
- SQL>alter index index_name noparallel;
明天,2007年7月11日,Oracle 11g将正式发布,也就是说,从明天起,我们就可以去下载11g,正式一睹11g的芳容了。在11g众多的新特性中,你最喜欢哪一点呢?
先简单列一下这些新特性吧:
- Use ASM Fast Mirror Resync to improve disk failure recovery times
- Set up ASM Fast Mirror Resync using SQL
- Configure preferred mirror groups using the ASM_PREFERRED_READ_FAILURE_GROUPS parameter
- Use the SYSASM privilege to manage ASM disks
- Use the compatibility modes for disk groups
- Use ASMCMD command extensions to back up and restore disk groups
- Discuss LOB improvements using SecureFiles
- Use temporary tablespace enhancements
- Perform proactive failure checks using the Data Recovery Advisor
- Enable tracking of table data using Flashback Data Archive
- Back out data changes using flashback transaction
- Configure archive log deletion policies
- Duplicate active databases using Oracle network (without backups)
- Back up large files in multiple sections
- Create archival backups for long-term storage
- Query a physical standby database while redo is applied
- Control the location of SQL Apply event information
- Set the retention target for remote archived log files
- Use the logical standby database flash recovery area
- Create a snapshot standby database
- Configure the password file to use case-sensitive passwords
- Use TDE support on a logical standby database
- Use TDE support for Streams
- Create a tablespace with encryption for added security
- Store external encrypted data using the Hardware Security Module
- Use LOB encryption for SecureFile LOBs on per-column or per-partition basis
- Use EM to manage your database security options
- Set up and modify Automatic SQL Tuning
- Create AWR Baselines for future time periods
- Use additional supplied maintenance windows for specific maintenance tasks
- Simplify memory configuration by setting MEMORY_TARGET initialization parameters
- Improve file accessibility of the SPFILE file
- Perform clusterwide analysis of performance using RAC-aware ADDM
- Implement partitioning on tables, indexes, and materialized views from SQL Access Advisor’s recommendations
- Use partitioning enhancements to gain significantly faster data access
- Gain flexibility in automatic statistic generation at the object level
- Use memory efficiently with Query Result Cache support
- Gain execution speed by using automatic native PL/SQL and Java compilation
- Discuss the increased cursor shareability
其中,最能吸引我的,莫过于
Query a physical standby database while redo is applied
这个巨大的改进,我相信,如果稳定以后,将把物理standby的稳定性,与实时只读特性完美结合,实现了最为完美的读写分离。
那个时候,加上stream的进一步改进,相信shared plex的麻烦可就来了。
一、怎么样刷新
mv可以用来同步数据,一般采用主键同步或者是ROWID同步,我们这里只讨论主键同步(Rowid同步其实是为Rowid在目标表上创建了一个隐含索引,原理跟主键同步一样)。mv的主要原理就是记录更改的日志,并同步到远程。
一个简单的例子:
- SQL>create materialized view log on table_name;
-
- SQL>create materialized view table_name [on prebuilt table] refresh fast as
- select * from table_name@lnk_db_master;
-
- SQL>exec dbms_mview.refresh('table_name',method => 'Complete');
- SQL>exec dbms_mview.refresh('table_name');
-
- SQL> declare jobid number;
- 2 begin
- 3 sys.dbms_job.submit(job => jobid,
- 4 what => 'dbms_mview.refresh(''table_name'');',
- 5 next_date => sysdate,
- 6 interval => 'sysdate+5/1440');
- 7 commit;
- 8 end;
- 9 /
其中
第1步是在需要复制的主表(master table)上创建mv log。
第2步是在远程站点(想复制到的那个站点)上创建mv,注意,如果选择了选项on prebuild table的话,表示在已经存在的表上创建mv,需要已经存在的表的字段与select的字段必须要对应,这个已经存在的表中可以没有数据。
第3步是全同步,如果没有选择on prebuild table,这一步可以省略,因为默认创建mv的时候,就会全刷新
第4步是增量刷新,在完成全刷新以后的情况下,一般都只需要做增量刷新即可。
第5步是创建一个自动刷新的作业来进行刷新,如每5分钟刷新一次,这个操作也可以同crontab来代替。
二、相关视图与基表信息
dba_mviews记录了远程站点上mv的数目与属性,需要在创建MV的站点上查询。
sys.mlog$则记录了主站点上的mv的log数目,如果一个master对应到多个站点,也只有一条记录,对应到dba_mview_logs视图,需要在主站点查询。
sys.slog$记录了主站点上已经注册成功的主表信息,如果一个主表被复制到多个站点,则对应多条记录,在主站点查询。
dba_snapshot_logs存放了mv的log日志,如果对应到多个站点,则每个站点都对应一条记录,因为远程站点的snapshot_id是不一样的。其实sys.mlog$与sys.slog$的关联就是组成dba_snapshot_logs的一个部分,通过查询dba_views可以看到其脚本。
dba_registered_snapshots记录了远程站点的注册信息,只记录注册成功的远程站点,通过snapshot_id可以与dba_snapshot_logs关联。如
- SQL>select t.log_owner,t.master,t.log_table,t.current_snapshots,
- r.owner,r.name,r.snapshot_site
- from dba_snapshot_logs t,dba_registered_snapshots r
- where t.snapshot_id= r.snapshot_id(+);
删除mv的时候,需要先删除mv,再删除mv日志
远程MV站点:
- SQL>drop materialized view table_name;
主站点:
- SQL>drop materialized view log on table_name;
注意,删除mv的时候,如果主站点需要分发到多个远程站点,只有当所有远程站点的MV删除完成后,才可以删除MV日志。
删除远程站点的MV的时候,要保证与主站点的通信顺畅,如果网络不通,则主站点无法正常Unregister MV,而主站点的mv log又因为不知道这个站点已经没有MV,而不删除mv日志,将可能引起主站点mlog表的膨胀。这个时候,可以手工强行解除注册。
- SQL>exec DBMS_SNAPSHOT.PURGE_SNAPSHOT_FROM_LOG (snapshot_id);
三、故障处理与维护
如果mlog因为日志曾经很多而变得很大的时候,对mlog的操作如日志删除将变得很慢,因为mlog上没有任何索引,走的都是全表扫描,这个时候,我们可以move该日志表或者是等日志表没有记录的时候truncate该表。
- SQL>alter table mlog$_table_name move;
如果要对有mv复制的表增加字段,最好在停机情况下进行,因为这样不会产生mv log,而且最好采用prebuild模式,因为这种模式下,删除mv的定义将保留表(也就是不删除表与相关数据)。相关步骤:
停机模式,并且在使用prebuild的情况下:
1、远程站点:
- SQL>drop materialized view mv_table; --这里删除mv,保留原表
2、主站点:
- SQL>alter table master_table add new_field number;
3、远程站点:
- SQL>alter table mv_table add new_field number;
4、远程站点:
- SQL>create materialized view mv_table on prebuilt table
- refresh fast as
- select * from master_table@lnk_db;
5、建立快速刷新的作业,这个时候不需要全刷新了,因为数据都在
为什么要停机操作,是因为创建快速刷新的mv的时候,将删除主站点上创建mv时间点之前的相关log,所以在删除mv与重新创建mv之前,不能对主表有任何dml产生新的日志,否则将可能引发数据的不一致。
在aix上,我们可以将oracle SGA pin在内存中,防止这部分内存交换。所以,通过pin住oracle SGA,能带来很大的性能好处。
如果想要正确的pin住内存,涉及到2个OS内核参数与一个oracle init参数:
1、aix参数v_pinshm=1,默认是0,表示aix将支持pin住内存,设置方法为
#vmo -p -o v_pinshm=1
2、aix参数maxpin%=内存百分比,默认80%,表示支持的最大的可pin住内存的比例,设置方法为
#vmo -p -o maxpin%=90
3、oracle参数LOCK_SGA=true,表示oracle将使用这部分被pin住的内存,其实就是告诉oracle使用另外一种内存调用方法。
因为这部分pin住的内存不仅仅是oracle在使用,aix内核也可能需要用到这部分内存,所以,我们不能设置SGA超过如下2个公式的范围:
1、SGA < 总内存*(maxpin%-10%),如果是默认值,则SGA不能超过总内存的70%
2、OS的pin住内存的总量(稳定运行时的总量,会随SGA大小而变化) < 总内存*(maxpin%-5%),如果是默认值,则pin住的内存总量,不能超过总内存的75%
至于Oracle的SGA总量,可以通过如下命令查看
- SQL> select sum(value)/1024/1024/1024 "SIZE(G)" from v$SGA;
-
- SIZE(G)
- ----------
- 71.2681394
至于被pin住的内存总量,可以通过OS的命令svmon来查看
#svmon -G
size inuse free pin virtual
memory 27394048 23520958 3873090 20424376 20884173
pg space 16777216 41932
......
注意,以上pin住的部分,是表示4k大小的页面个数(没有使用大页的情况下),那么,折算成内存大小则是20424376*4/1024/1024=77.91G。
那么,如果采用默认的maxpin%设置(80%),我们将需要多大的物理内存呢?
公式1:物理内存 = 71.27/0.7 = 102G
公式2:物理内存 = 77.91/0.75 = 104G
在两者里面取大值,表示我们至少需要104G的物理内存,再去掉其它转换消耗,固定消耗,购买内存起码需要108G。
关于以上2个公式,我还想补充说明一下,在5.2的早些版本中,只需要满足公式1即可,如果实际设置的SGA内存超过了公式1的范围,其实OS也只pin住maxpin%-10%的内存,其它的没有pin住的内存,可能会导致交换的发生,最多是影响性能。
但是,aix 5.2以后的一些版本以及aix 5.3版本,因为不同page size的出现(如64K的page size的大量使用),如果不符合以上的两个公式,最严重的后果就是会导致OS被hang住,其实也就是aix的一个新的psm后台进程,一个负责页面转换的进程,当发现内存不够的时候,会直接杀掉运行的进程。
够狠,也够烂。
这个问题最早应当是gototop发现的,那已经是很多年以前的事情了,不过,一直到现在,这个问题其实没有最终解决,所以,这个补丁还是不得不一直打下去。bug描述:
# Bugs resolved by this patch in conjunction with APAR IY49415:
# -------------------------------------------------------------
# 3028673: ORACLE ON AIX DOES NOT SHARE MANY CONST STRUCTS - PER
# PROCESS MEMORY OVERHEAD
更详细的信息可以参考metalink Note:259983.1,其实在早先的aix 4.3以及5.1上,当时的解决方案是:
$AIXTHREAD_SCOPE=S; export AIXTHREAD_SCOPE
$NUM_SPAREVP=1; export NUM_SPAREVP
但是,从aix 5.2开始,以上解决方案不再有效,所以,为了解决这个问题,aix 5.2推出了一个APAR IY49415,在aix 5.3中是查不到这个APAR信息的,但是不表示aix 5.3不支持,而是因为aix 5.3已经完全包含进去了。
AIX 5.2#instfix -a -ivk IY49415
IY49415 Abstract: read-only reloc linking/loading support
IY49415 Symptom Text:
Programs having large amounts of read-only address constants
(compared to our competitors binaries of the same programs),
consume excessive amounts of memory under AIX since it has no
support to place address constants in read-only memory (text).
----------------------------
Fileset bos.64bit:5.2.0.12 is applied on the system.
Fileset bos.mp:5.2.0.18 is applied on the system.
Fileset bos.mp64:5.2.0.18 is applied on the system.
Fileset bos.rte.bind_cmds:5.2.0.13 is applied on the system.
Fileset bos.up:5.2.0.18 is applied on the system.
All filesets for IY49415 were found.
在有该APAR的aix 5.2系统上,或者所有的aix 5.3系统上,oracle推出了一个patch 3028673。打这个patch的方法也很奇怪,不是传统的Opatch方式去打,而是重新relink一个新的Oracle可执行文件,最终目的是通过直接修改源文件,使得oracle的多个进程之间可以共享一部分原来不能共享的资源,这部分资源大致占用1M多的空间。所以,该patch可以使得每个oracle进程降低1M多一点的内存使用,如果在进程特别多,而内存又比较紧张的系统上,这个patch还是非常有效果的。relink的方法为:
Relink the oracle binary
~~~~~~~~~~~~~~~~~~~~~~~~
1 save your current version of $ORACLE_HOME/oracle
2 create a working directory $ORACLE_HOME/relink
3 cd to $ORACLE_HOME/relink
4 unzip the relinking package
5 link $ORACLE_HOME/bin/oracle to ./oracle0
6 run the script ./genscript to generate some required files and scripts
7 run ./relink.sh to generate the new oracle binary oracle0.new.$$
8 copy oracle0.new.$$ to $ORACLE_HOME/bin/oracle and verify that the
permissions match the original oracle binary.
另外,需要特别注意的是,patch中描述为
# Patch Special Instructions
# ---------------------------
# This patch is for AIX 5.2 systems only.
#
# It is valid for all 920* AIX 5.2 systems.
这个是因为当时还没有aix 5.3系统,其实,实际上所有oracle 920系统+aix 5.2/5.3都可以使用这个patch,以下是使用前后的对照表,注意SIZE列,补丁前与补丁后基本相差1M多,如果有1000个进程,就可以节约1-2G的内存使用。
补丁前$ps gx|grep oracle
PID TTY STAT TIME PGIN SIZE RSS LIM TSIZ TRS %CPU %MEM COMMAND
483436 - A 199:48 12 4804 25876 xx 49801 21136 0.5 0.0 oracletb
602170 - A 198:55 0 4804 25940 xx 49801 21136 0.5 0.0 oracletb
610420 - A 209:55 6 4844 25980 xx 49801 21136 0.5 0.0 oracletb
630988 - A 145:18 9 4860 25932 xx 49801 21136 0.4 0.0 oracletb
639154 - A 199:59 10 4828 25900 xx 49801 21136 0.5 0.0 oracletb
643276 - A 191:42 4 4792 25864 xx 49801 21136 0.5 0.0 oracletb
651494 - A 193:13 6 4844 25916 xx 49801 21136 0.5 0.0 oracletb
671756 - A 204:38 10 4776 25848 xx 49801 21136 0.5 0.0 oracletb
……
补丁后$ps gv|grep oracle
PID TTY STAT TIME PGIN SIZE RSS LIM TSIZ TRS %CPU %MEM COMMAND
639170 - A 0:01 3 3036 77100 xx 50917 74064 0.1 0.0 oracletb
643300 - A 0:00 0 3012 77076 xx 50917 74064 0.0 0.0 oracletb
651514 - A 0:03 1 3196 77196 xx 50917 74064 0.1 0.0 oracletb
671762 - A 0:05 2 3120 77184 xx 50917 74064 0.2 0.0 oracletb
675850 - A 0:04 0 3120 77120 xx 50917 74064 0.2 0.0 oracletb
680040 - A 0:06 0 3120 77184 xx 50917 74064 0.2 0.0 oracletb
688218 - A 0:05 0 3116 77180 xx 50917 74064 0.2 0.0 oracletb
700614 - A 0:09 2 3120 77120 xx 50917 74064 0.2 0.0 oracletb
……
在以前的应用中,ASSM表空间已经被广泛的使用,但是,我从来没有真正发现过三级位图块。借这次的存储测试,在测试表装载的时候,随便弄了一个超大的表(873G),但是,遗憾的是,还是没有发现三级位图块。
- SQL> select bytes/1024/1024/1024 "SIZE(G)" from user_segments where segment_name='TEST';
-
- SIZE(G)
- ----------
- 873.25
-
- SQL> select file_id,block_id from dba_extents where segment_name='TEST' and extent_id=0;
-
- FILE_ID BLOCK_ID
- ---------- ----------
- 74 9
-
- SQL>alter system dump datafile 74 block 74;
打开跟踪文件,可以看到
......
type: 0x23=PAGETABLE SEGMENT HEADER
......
Last Level 1 BMB: 0x251f200c
Last Level II BMB: 0x251d700d
Last Level III BMB: 0x00000000
......
Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x12800049
DBA 2: 0x1c00c00d
DBA 3: 0x1c02100d
......
DBA 109: 0x2cdad00d
DBA 110: 0x2cdc200d
DBA 111: 0x2cdd700d
DBA 112: 0x2cdec00d
从以上的信息可以看到,在一个叫PAGETABLE SEGMENT HEADER的块中,已经出现了112个二级位图块,但是,还是没有一个三级位图块。
以上的信息中,可能有人比较疑惑的是,怎么定位这个叫 PAGETABLE SEGMENT HEADER的块。大致方法可以为:
1、从dba_extents中获得的extent_id=0的信息,可以得到file_id=74,block_id=9,这个表示这个段的开始块。
2、dump datafile 74 block 9,可以看到这个是一个FIRST LEVEL BITMAP BLOCK,里面保存了它所管理的block,其中大致为:
......
type: 0x20=FIRST LEVEL BITMAP BLOCK
......
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x12800009 Length: 64 Offset: 0
0:Metadata 1:Metadata 2:Metadata 3:Metadata
4:Metadata 5:Metadata 6:Metadata 7:Metadata
8:Metadata 9:Metadata 10:Metadata 11:Metadata
......
可以看到,这里有很多类型为Metadata的块,这些都是oracle的管理块,要么是位图块,要么是段头,选择这里面的最后一个Metadata的块,一般就是PAGETABLE SEGMENT HEADER,如我上面的例子,block=74(74=8+Metadata前面的Id)。
3、再dump datafile 74 block 74即可。
我个人猜想位图管理的大致结构应当如下,但是我从来没有证明过,要是有谁发现了三级位图块,或者是有这方面的资料,可以反馈给我,谢谢。
感谢eygle的测试,L3已经找到了,ASSM正确的结构图应当如下: