10g引入ASMM后SGA_TARGET取代shared_pool_size,db_cache_size等参数,成为DBA关注的主要SGA内存管理参数;有不少情况下SGA_TARGET参数会设置为一个小于SGA_MAX_SIZE的值(这样做在多实例情况下更具灵活性)。但不少人会问,这样岂不是要浪费一部分物理内存吗?Oracle会为实例分配SGA_MAX_SIZE大小的内存的,SGA_TARGET要设得和SGA_MAX_SIZE一样大才合理啊! 让我们来看看实际的情况:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
SQL>  select  from  v$version;
BANNER
----------------------------------------------------------------
Oracle  Database  10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS  for  Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
 
/*  linux上的10.2.0.4  */
 
SQL> show parameter sga
NAME                                  TYPE        VALUE
------------------------------------ ----------- ------------------------------
lock_sga                             boolean      FALSE
pre_page_sga                         boolean      FALSE
sga_max_size                         big  integer  3600M
sga_target                           big  integer  368M
 
SQL> col component  for  a25;
SQL>  select  component, current_size / 1024 / 1024, last_oper_type
   2     from  v$sga_dynamic_components
   3    where  current_size != 0;
 
COMPONENT                 CURRENT_SIZE/1024/1024 LAST_OPER_TYP
------------------------- ---------------------- -------------
shared pool                                   96  STATIC
large pool                                    16  STATIC
java pool                                     16  STATIC
DEFAULT  buffer cache                         224 INITIALIZING
 
/* 此时的SGA_TARGET为368M,而SGA_MAX_SIZE为3600M */
 
/* 我们来看一下实际的物理内存使用情况  */
 
/* 以root用户登录,因为我们需要用到清理文件系统缓存的命令 */
 
[maclean@rh2 ~]$ su - root
Password :
 
[root@rh2 ~]# sync
[root@rh2 ~]# sync
 
/* sync 命令用以写出文件系统脏缓存,类似于Oracle的 checkpoint 手动检查点 */
 
[root@rh2 ~]# echo 3 > /proc/sys/vm/drop_caches
[root@rh2 ~]# echo 3 > /proc/sys/vm/drop_caches
 
/*  将proc文件系统下的drop_caches文件置为3,清理文件系统缓存,以免其干扰我们的实验 */
 
[root@rh2 ~]#  free
              total       used        free      shared    buffers     cached
Mem:       4046352     429328    3617024          0        296     176100
-/+ buffers/cache:     252932    3793420
Swap:     10241428          0   10241428
 
/*  4g内存中仅有419M处于使用状态,其他均为 free 。可见Oracle没有为实例分配大小等于SGA_MAX_SIZE的内存空间,而接近于SGA_TARGET_SIZE的大小 */
[root@rh2 ~]# ps -ef|grep pmon|grep -v grep
maclean   6361     1  0 18:35 ?        00:00:00 ora_pmon_YOUYUS
 
[root@rh2 ~]# pmap -x 6361
6361:   ora_pmon_YOUYUS
Address           Kbytes     RSS   Dirty Mode   Mapping
0000000000400000  100412    7300       0 r-x --  oracle
000000000680f000     544     180      64 rwx --  oracle
0000000006897000     148     104     104 rwx --    [ anon ]
000000001e9d0000     672     532     532 rwx --    [ anon ]
0000000060000000 3688448    1044     388 rwxs-    [ shmid=0x390005 ]
 
/* 利用pmap工具探测Oracle后台进程的内存地址空间,可以看到这里虚拟共享内存段(也就是SGA)的大小为3602M */
 
[root@rh2 ~]# ipcs -m
 
------ Shared Memory Segments --------
key         shmid      owner      perms      bytes      nattch     status
0x74018366 3112960    root      600        4          0
0x00000000 3473409    root      644        80         2
0x74018365 3080194    root      600        4          0
0x00000000 3506179    root      644        16384      2
0x00000000 3538948    root      644        280        2
0x1cdd16e8 3735557    maclean   640        3776970752 15
 
/* 使用ipcs 命令也可以观察到这个大小为3602M的共享内存段 */
 
/* 可以猜测Oracle在这里使用malloc函数或类似的方法实现虚拟内存的分配,没有像calloc函数那样对空间中的每一位都初始为0,保证了不浪费物理内存  */
 
/*  我们动态修改SGA_TARGET参数来看看*  /
 
SQL>  alter  system  set  sga_target=3000M;
 
System altered.
 
SQL>  select  component, current_size / 1024 / 1024, last_oper_type
   2     from  v$sga_dynamic_components
   3    where  current_size != 0;
 
COMPONENT                 CURRENT_SIZE/1024/1024 LAST_OPER_TYP
------------------------- ---------------------- -------------
shared pool                                   96  STATIC
large pool                                    16  STATIC
java pool                                     16  STATIC
DEFAULT  buffer cache                        2864 INITIALIZING
 
/*   BUFFER_CACHE 的空间大幅增加 * /
 
SQL> ! free
              total       used        free      shared    buffers     cached
Mem:       4046352    3187784     858568          0        536    2889920
-/+ buffers/cache:     297328    3749024
Swap:     10241428          0   10241428
 
/* used mem部分上升到3113M,随着SGA_TARGET的动态增长而增长了 */
 
/* 如果我们改小SGA_TARGET呢? */
 
SQL>  alter  system  set  sga_target=368M;
 
System altered.
 
SQL>  select  component, current_size / 1024 / 1024, last_oper_type
   2     from  v$sga_dynamic_components
   3    where  current_size != 0;
 
COMPONENT                 CURRENT_SIZE/1024/1024 LAST_OPER_TYP
------------------------- ---------------------- -------------
shared pool                                   96  STATIC
large pool                                    16  STATIC
java pool                                     16  STATIC
DEFAULT  buffer cache                         224 SHRINK
 
/* 可以看到BUFFER CACHE最近执行了SHRINK收缩操作, SIZE 下降到224M */
 
QL> ! free
              total       used        free      shared    buffers     cached
Mem:       4046352    3204608     841744          0       1596    2912888
-/+ buffers/cache:     290124    3756228
Swap:     10241428          0   10241428
 
/* 此时OS层仍认为used memory部分为3130M;但可以放心,它们是可被其他进程复用的  * /
官方对pre_page_sga参数的定义是"PRE_PAGE_SGA determines whether Oracle reads the entire SGA into memory at instance startup. Operating system page table entries are then prebuilt for each page of the SGA. This setting can increase the amount of time necessary for instance startup, but it is likely to decrease the amount of time necessary for Oracle to reach its full performance capacity after startup." 它决定Oracle是否在启动阶段将整个SGA读入内存,实际上在启动阶段SGA的内容是十分稀疏的,当pre_page_sga为TRUE时Oracle所要做的是向OS所要SGA_MAX_SIZE大小的实际物理页。 我们来看一下这个参数的实际效果:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
SQL>  alter  system  set  sga_max_size=2500M scope=spfile;
System altered.
 
SQL>  alter  system  set  pre_page_sga= true  scope=spfile;
System altered.
 
SQL> startup  force  ;
ORACLE instance started.
 
Total System  Global  Area 2634022912 bytes
Fixed  Size                   2086288 bytes
Variable  Size             2382367344 bytes
Database  Buffers          234881024 bytes
Redo Buffers               14688256 bytes
Database  mounted.
Database  opened.
 
[root@rh2 ~]# echo 3 > /proc/sys/vm/drop_caches
 
SQL> show parameter sga
 
NAME                                  TYPE        VALUE
------------------------------------ ----------- ------------------------------
lock_sga                             boolean      FALSE
pre_page_sga                         boolean      TRUE
sga_max_size                         big  integer  2512M
sga_target                           big  integer  368M
 
SQL> ! free
              total       used        free      shared    buffers     cached
Mem:       4046352    2895256    1151096          0        648    2623692
-/+ buffers/cache:     270916    3775436
Swap:     10241428     104936   10136492
 
/*  设置pre_page_sga参数为 true 后,Oracle实际分配的物理内存不再局限于SGA_TARGET,而是在实例生命周期内几乎恒等于SGA_MAX_SIZE指定的值了 * /
 
/*  当SGA_TARGET配合pre_page_sga使用时,这的确可能造成一种浪费 ! * /

10g中Oracle已经强烈不建议使用pre_page_sga参数了,在ASMM下它带来的问题可不小!