Oracle中的ASMM和AMM介绍以及ORA-00845: MEMORY_TARGET not supported on this system错误
Tags: AMMASMMMEMORY_TARGETORA-00845Oracle自动共享内存管理自动内存管理
什么是ASMM和AMM?
ASMM(Automatic Shared Memory Management,自动共享内存管理)是Oracle 10g引入的概念。通过使用ASMM,就不需要手工设置相关内存组件的大小,而只为SGA设置一个总的大小,
Oracle的MMAN进程(Memory Manager Process,内存管理进程)会随着时间推移,根据系统负载的变化和内存需要,自动调整SGA中各个组件的内存大小。
ASMM的SGA中包含的组件及对应参数如下表所示:
在Oracle 10g中,必须将STATISTICS_LEVEL参数设置为TYPICAL(默认值)或者ALL才能启用ASMM功能,如果将其值设置为BASIC,那么会禁用很多新特性,比如像AWR、ASMM等。
如果使用SQL*Plus来设置ASMM,那么必须先把SGA中包含的组件的值设置为0。通过设置SGA_TARGET参数为非零值来启用ASMM功能。
可以通过以下SQL来计算SGA_TARGET的值:
1 | SELECT ((SELECT SUM(VALUE) FROM V$SGA) - (SELECT CURRENT_SIZE FROM V$SGA_DYNAMIC_FREE_MEMORY)) "SGA_TARGET" FROM DUAL; |
设置SGA_TARGET的值,可以直接修改初始化参数文件后重启数据库,或者通过下面SQL命令进行修改:
1 | ALTER SYSTEM SET SGA_TARGET=value [SCOPE={SPFILE|MEMORY|BOTH}]; |
示例如下所示:
1 2 3 4 5 6 | ALTER SYSTEM SET SGA_TARGET = 992M; ALTER SYSTEM SET SHARED_POOL_SIZE = 0; ALTER SYSTEM SET LARGE_POOL_SIZE = 0; ALTER SYSTEM SET JAVA_POOL_SIZE = 0; ALTER SYSTEM SET STREAMS_POOL_SIZE = 0; ALTER SYSTEM SET DB_CACHE_SIZE = 0; |
在启用ASMM后,Oracle会自动调整SGA内部组件大小。若再手动指定某一组件值,则该值为该组件的最小值。例如,手动设置SGA_TARGET=8G,SHARED_POOL_SIZE=1G,
则ASMM在自动调整SGA内部组件大小时,保证Shared Pool不会低于1G。当设置了SGA_TARGET参数后,Oracle将会收集SGA相关的统计数据,并通过V$SGA_TARGET_ADVICE呈现出来,
因此,可以根据这些指导SGA_TARGET做相关的调整,以达到最佳情况。
Oracle 10g的ASMM实现了自动共享内存管理,但是具有一定的局限性。所以,在Oracle 11g中,Oracle引入了AMM(Automatic Memory Management,自动内存管理)的概念,实现了全部内存的自动管理。DBA可以仅仅通过设置一个目标内存大小的初始化参数(MEMORY_TARGET)和可选最大内存大小初始化参数(MEMORY_MAX_TARGET)就可以在大多数平台上实现AMM。
AMM可以使实例总内存保持相对稳定的状态,Oracle基于MEMORY_TARGET的值来自动调整SGA和PGA的大小。MEMORY_TARGET是动态初始化参数,可以随时修改该参数的值而不用重启数据库。
MEMORY_MAX_TARGET作为一个内存上限值,是一个静态参数,它是MEMORY_TARGET可以被配置的最大值。
如果内存发生变化,实例会自动在SGA和PGA之间做调整。若启用了AMM功能,而SGA_TARGET和PGA_AGGREGATE_TARGET没有显式的被设置,
则默认SGA_TARGET为MEMORY_TARGET的60%,PGA_AGGREGATE_TARGET为MEMORY_TARGET的40%。
如果MEMORY_MAX_TARGET设置为1400M,而MEMORY_TARGET设置为1000M,那么对于数据库实例而言,只有1000M可以使用,剩下的400M会被保留下来,
但会被Oracle的MMAN进程锁定。但是,因为MEMORY_MAX_TARGET是显式设置的,所以,可以在不重启数据库的情况下动态调整MEMORY_TARGET。
如果只设置了MEMORY_TARGET的值,而MEMORY_MAX_TARGET没有显式设置,那么MEMORY_MAX_TARGET的值默认是MEMORY_TARGET的大小。
当LOCK_SGA初始化参数的值设置为TRUE时,不能启用AMM,该参数的值默认为FALSE。
只要是设置了MEMORY_MAX_TARGET或MEMORY_TARGET,那么就说明启用了AMM。可以使用视图V$MEMORY_DYNAMIC_COMPONENTS动态查阅内存各组件的当前实时大小。
启用AMM
如果在创建数据库的时候未启用AMM,那么可以在建库后启用它,启用AMM需要重启数据库,具体步骤如下所示:
1、查询SGA_TARGET和PGA_AGGREGATE_TARGET的值,从而确定MEMORY_TARGET的最小值
1 2 3 4 5 | SYS@lhrdb> SHOW PARAMETER TARGET NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ pga_aggregate_target big integer 409M sga_target big integer 1648M |
2、确定自系统启动以来PGA的最大值,单位为bytes
1 2 3 4 | SYS@lhrdb> select value from v$pgastat where name='maximum PGA allocated'; VALUE ---------- 248586240 |
3、通过以下方法来计算出SGA_TARGET的最大值
1 | memory_target = sga_target + max(pga_aggregate_target, maximum PGA allocated) |
例如:在这里,SGA_TARGET的值为1648M,PGA_AGGREGATE_TARGET的值为409M,PGA的最大值为248586240/1024/1024=237M,所以,MEMORY_TARGET的值至少为1648+409=2057M。
4、设置系统参数启用AMM
1 2 3 4 5 | ALTER SYSTEM SET MEMORY_MAX_TARGET = 2100M SCOPE=SPFILE; --重启数据库 ALTER SYSTEM SET MEMORY_TARGET = 2057M; ALTER SYSTEM SET SGA_TARGET = 0; ALTER SYSTEM SET PGA_AGGREGATE_TARGET = 0; |
ORA-00845: MEMORY_TARGET not supported on this system
另外需要说明的一点是,使用AMM经常出现的一个错误是“ORA-00845: MEMORY_TARGET not supported on this system”。
1 2 3 4 | [ZFZHLHRDB1:oracle]:/oracle>oerr ora 845 00845, 00000, "MEMORY_TARGET not supported on this system" // *Cause: The MEMORY_TARGET parameter was not supported on this operating system or /dev/shm was not sized correctly on Linux. // *Action: Refer to documentation for a list of supported operating systems. Or, size /dev/shm to be at least the SGA_MAX_SIZE on each Oracle instance running on the system. |
这个错误原因是操作系统不支持MEMORY_TARGET参数或/dev/shm的大小设置不正确。解决方法就是将/dev/shm的值增大,至少需要大于数据库参数MEMORY_MAX_TARGET的值。修改步骤如下:
1 2 3 4 5 6 7 8 9 10 11 | [root@LHRDB ~]# cat /etc/fstab | grep tmpfs #查看/dev/shm大小 tmpfs /dev/shm tmpfs defaults,size=1G 0 0 [root@LHRDB ~]# mount -o remount,size=4G /dev/shm #临时修改/dev/shm大小 [root@LHRDB ~]# vi /etc/fstab #永久修改/dev/shm大小, tmpfs /dev/shm tmpfs defaults,size=4G 0 0 [root@LHRDB ~]# df -h | grep shm tmpfs 4.0G 0 4.0G 0% /dev/shm [root@LHRDB ~]# df -h /dev/shm/ Filesystem Size Used Avail Use% Mounted on tmpfs 4.0G 0 4.0G 0% /dev/shm [root@LHRDB ~]# cat /etc/fstab | grep tmpfs tmpfs /dev/shm tmpfs defaults,size=4G 0 0 |
再次启动数据库就可以正常启动了。
ASMM和AMM的区别
由于AMM不支持HugePage,而ASMM支持HugePage,所以,在生产库上强烈推荐使用ASMM。
有关ASMM和AMM的区别如下表所示:
MOS文档“SGA and PGA Management in 11g's Automatic Memory Management (AMM) (文档 ID 1392549.1)”对AMM和ASMM有非常详细的说明。
Oracle 11g AMM与ASMM切换
现在的Oracle正在往智能化方向发展。如果我们现在找一些8i/9i时代的Oracle书籍,怎么样配置合适的数据库各内存池大小是非常重要的话题。但是进入10g之后,自动内存池调节成为一个重要Oracle特性。
在10g时,Oracle推出了ASMM(Automatic Shared Memory Management),实现了Oracle SGA和PGA内部结构的自调节。进入11g之后,AMM(Automatic Memory Management)实现了参数MEMORY_TARGET,将SGA和PGA的规划全部统筹起来对待。
默认情况下,Oracle 11g是使用AMM的。我们在安装过程中,指定Oracle使用内存的百分比,这个取值就作为MEMORY_TARGET和MEMORY_MAX_TARGET的初始取值使用。如果这两个参数设置为非零取值,那么Oracle就是采用AMM管理策略的。
同时,如果我们设置这两个参数为0,则AMM自动关闭。对应的SGA_TARGET、PGA_AGGREGATE_TARGET参数取值非零之后,Oracle自动退化使用ASMM特性。
本篇简单介绍一下AMM和ASMM的相互切换。
1**、实验环境介绍**
我们选择11.2.0.3进行试验,当前状态为ASMM。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
当前MEMORY_TARGET设置为零,AMM没有启用。
SQL> show parameter target
NAME TYPE VALUE
archive_lag_target integer 0
db_flashback_retention_target integer 1440
fast_start_io_target integer 0
fast_start_mttr_target integer 0
memory_max_target big integer 0
memory_target big integer 0
parallel_servers_target integer 16
pga_aggregate_target big integer 108M
sga_target big integer 252M
2**、从ASMM**到AMM
在11g中,如果使用ASMM,对应的内存共享段是真实的共享段。
[oracle@SimpleLinux ~]$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 32768 oracle 640 4194304 32
0x00000000 65537 oracle 640 260046848 32
0x01606d30 98306 oracle 640 4194304 32
下面进行参数的调整,这里笔者有一个建议,很多时候启动umount阶段故障都是由于不当的参数修改造成的。在进行参数修改之前,可以使用create pfile进行一下参数备份,可以加快故障出现时候的系统修复速度。
SQL> show parameter spfile
NAME TYPE VALUE
spfile string /u01/app/oracle/dbs/spfileora11g.ora
SQL> create pfile from spfile;
Done
修改系统参数,将sga和pga的target值设置为0,memory的target设置非0。注意,这个过程很多参数是静态的参数,可以都在spfile可见性中进行修改,之后重启服务器生效。
SQL> alter system set memory_max_target=360m scope=spfile;
System altered
SQL> alter system set memory_target=360m scope=spfile;
System altered
SQL> alter system set sga_target=0m scope=spfile;
System altered
SQL> alter system set sga_max_size=0 scope=spfile;
System altered
SQL> alter system set pga_aggregate_target=0 scope=spfile;
System altered
重新启动数据库服务器,查看参数配置。
SQL> conn / as sysdba
Connected.
SQL> startup force
ORACLE instance started.
Total System Global Area 263651328 bytes
Fixed Size 1344284 bytes
Variable Size 176164068 bytes
Database Buffers 83886080 bytes
Redo Buffers 2256896 bytes
Database mounted.
Database opened.
SQL> show parameter target
NAME TYPE VALUE
archive_lag_target integer 0
db_flashback_retention_target integer 1440
fast_start_io_target integer 0
fast_start_mttr_target integer 0
memory_max_target big integer 360M
memory_target big integer 360M
parallel_servers_target integer 16
pga_aggregate_target big integer 0
sga_target big integer 0
AMM启动之后,系统共享段变为“虚拟”共享段。
[oracle@SimpleLinux dbs]$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 163840 oracle 640 4096 0
0x00000000 196609 oracle 640 4096 0
0x01606d30 229378 oracle 640 4096 0
3**、从AMM**到ASMM
下面是如何从AMM到ASMM。要完全关闭AMM,一定将MEMORY_TARGET和MEMORY_MAX_TARGET都设置为0才行。
SQL> alter system set memory_max_target=0 scope=spfile;
System altered
SQL> alter system set memory_target=0 scope=spfile;
System altered
SQL> alter system set pga_aggregate_target=100m scope=spfile;
System altered
SQL> alter system set sga_target=260m scope=spfile;
System altered
SQL> alter system set sga_max_size=260m scope=spfile;
System altered
注意,此时如果重新启动系统,会报错。
SQL> startup force
ORA-00843: Parameter not taking MEMORY_MAX_TARGET into account
ORA-00849: SGA_TARGET 272629760 cannot be set to more than MEMORY_MAX_TARGET 0.
SQL>
这个问题的原因是Oracle启动过程中对于参数的内部检查。因为MEMORY_MAX_TARGET被“显示”的赋值,与SGA_TARGET赋值相冲突。
解决的方法就是使用参数默认值。创建出pfile之后,将显示赋值为0的MEMORY_TARGET和MEMORY_MAX_TARGET记录行删除掉。再利用pfile启动数据库,重建spfile。
SQL> create pfile from spfile
2 ;
File created.
--修改前
*.db_recovery_file_dest='/u01/app/fast_recovery_area'
*.db_recovery_file_dest_size=10737418240
*.diagnostic_dest='/u01/app'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=ora11gXDB)'
*.log_checkpoints_to_alert=TRUE
*.memory_max_target=0
*.memory_target=0
*.open_cursors=300
*.pga_aggregate_target=104857600
*.processes=150
--修改后
*.db_recovery_file_dest='/u01/app/fast_recovery_area'
*.db_recovery_file_dest_size=10737418240
*.diagnostic_dest='/u01/app'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=ora11gXDB)'
*.log_checkpoints_to_alert=TRUE
*.open_cursors=300
*.pga_aggregate_target=104857600