We know that, Oracle introduced Sga_target parameter to manage Buffer cache (DB_CACHE_SIZE), Shared pool (SHARED_POOL_SIZE),Large pool (LARGE_POOL_SIZE) and Java pool (JAVA_POOL_SIZE). It s considered as an important concept in Automatic Memory Management (AMM)
I could see the shared memory segment that I allocated in ipcs output..
This server was an Oracle Database server, and I saw the shared memory segments allocated by the running Oracle Database , too. Oracle Database allocated approx 7*2 gb(14gb in total) shared memory segments.. I checked its SGA to be sure.. Both, the sga_target and sga_max_size parameters were set to 14gb. On the other hand, the kernel parameter shmmax was set to 2gb.. That was why Oracle allocated the 14 gb memory segment in 7 pieces.. (Note that : Shmmax describes maximum size of a shared memory segment)
Lets come back to the our actual topic; I was allocating and deallocating the shared memory segments. I could do it with shmget. But one thing that I cant do with it , is that I could not resize a shared segment on-the-fly. Ofcourse, I could deallocate and reallocate a segment with a new size, but this is not satisfying..
To able to resize a shared memory segment, I decided to use shm_open(create or gain access to a shared memory segment) and ftruncate(truncate a file to a specified length), posix memory operation functions..
So shm_open uses a file based approach and technology for shared memory operations. It basically uses tmpfs,/dev/shm to function. Because it s using a file based architecture, there is an opportunity to use the ftruncate for resizing the file, which is actually tied to a shared memory segment.. By doing this, a shared memory segment can be resized on-the-fly.
I used following C program , which uses shm_open and ftruncate functions to allocate and resize the shared memory segment ;
Note that : this program should be compiled using gcc -lrt , by using -lrt argument posix support is added to the gnu c compiler.
This time , I checked the file named shmerman, which was located under /dev/shm and saw that its size was 300000b after created and it jumped to 600000b after 10 seconds..(sleep 10)
Note that: You cant see the shared memory segment allocated by shm_open in ipcs output. You can check the segments from the /dev/shm filesystem.
In 11g , we have memory_target and I believe Oracle uses a similar method, that I just mentioned above, to manage the shared memory . As you know; to be able to use above method, you need to have a /dev/shm.. So /dev/shm is required for using memory_target in Oracle.
Beyond that, I think and read maybe, that Oracle uses /dev/shm to pass segments from SGA(shared memory) to PGA (process memory).. I think it just gives back the shared memory back to OS ,and OS gives it to the processes in case they needed. Giving back the unused memory should be enough for managing the PGA,as is not a limit and it s is not a fixed memory area resides in memory..
So far so good.. On the other hand, 10g Oracle does not use memory_target , naturally it does not use a /dev/shm based memory access..
ipcs output shows that it uses shmget to get the needed shared segments... Also , I have sent a mail to Tanel Poder regarding this topic, and he said by using strace in Oracle startup; shmget call can be seen..
Following was taken in startup process of an Oracle 10gR2 database.
open("/proc/sys/kernel/shmmax", O_RDONLY) = 2 --> It reads the shmmax to obtain the max segment size.
[pid 12584] shmget(2505607756, 6444548096, IPC_CREAT|IPC_EXCL|SHM_HUGETLB|0600) = -1 ENOMEM (Cannot allocate memory) --> It tries the Hugetlbs and can not get them as it s not configured.
[pid 12584] shmget(2505607756, 6444548096, IPC_CREAT|IPC_EXCL|0660) = 557059, then it uses small pages to allocate the 6gb sga , which shmid= 557059
shmat(557059, 0x7fbfffdf01, 0) = ? --> it attaches to the allocated shared memory
So it s clear Oracle 10g uses shmget to allocate the shared memory segments..
The question is that , how it can resize them?
As we know we can decrease the size of sga on-the-fly using sga_target parameter.
I tested and analyzed it to satisfy my curiosity;
1) sga_target = sga_max_size
As it is well known by the most of the community, I will not go in details about this parameter, except one thing = Reducing the memory usage using sga_target parameter.
Actually, the reason that made me write this post is, the shared memory.. I was testing some memory boundries and behaviours of the operating system in case of a shared memory deallocation.. I was working on it because the information was needed to analyze an EBS production system performance.. So, I was working on a Linux 64 bit, writing a program to allocate some shared memory memory ...
I used SYSV compatible shmget and allocated some shared memory.. I could use shmctl to deallocate this shared memory without any problems..
I could use ipcs on Linux to display and saw memory allocation and deallocation activities.
On the other hand, I realized that I could not resize the allocated shared memory on-the-fly. It seems using shmget , you cant do this in Linux. There is no such option to resize a shared memory segment using shmget in Linux.. In Aix,there is a shm_size argument for shmget . It s for resizing. But it seems it is not available for Linux.
So, I used the following C code to allocate and deallocate 1.5G shared memory.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define SHMSZ 1589934592
int main()
{
int shmid;
int shamerman;
key_t key = 5690;
shmid = shmget(key,SHMSZ,0666 | IPC_CREAT);
fprintf(stdout,"%d",shmid);
shmctl(shmid,SHM_SIZE,589934592);
sleep(3);
if ((shamerman=shmctl(shmid,IPC_RMID,0)) !=0)
{
fprintf(stderr,"ERROR with shmctl (%d: %s)\n", (int)(errno), strerror(errno));
return 1;
}
return 0;
}
This server was an Oracle Database server, and I saw the shared memory segments allocated by the running Oracle Database , too. Oracle Database allocated approx 7*2 gb(14gb in total) shared memory segments.. I checked its SGA to be sure.. Both, the sga_target and sga_max_size parameters were set to 14gb. On the other hand, the kernel parameter shmmax was set to 2gb.. That was why Oracle allocated the 14 gb memory segment in 7 pieces.. (Note that : Shmmax describes maximum size of a shared memory segment)
Lets come back to the our actual topic; I was allocating and deallocating the shared memory segments. I could do it with shmget. But one thing that I cant do with it , is that I could not resize a shared segment on-the-fly. Ofcourse, I could deallocate and reallocate a segment with a new size, but this is not satisfying..
To able to resize a shared memory segment, I decided to use shm_open(create or gain access to a shared memory segment) and ftruncate(truncate a file to a specified length), posix memory operation functions..
So shm_open uses a file based approach and technology for shared memory operations. It basically uses tmpfs,/dev/shm to function. Because it s using a file based architecture, there is an opportunity to use the ftruncate for resizing the file, which is actually tied to a shared memory segment.. By doing this, a shared memory segment can be resized on-the-fly.
I used following C program , which uses shm_open and ftruncate functions to allocate and resize the shared memory segment ;
Note that : this program should be compiled using gcc -lrt , by using -lrt argument posix support is added to the gnu c compiler.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h>
int main()
{
int *result = NULL;
int integerSize = sizeof(300000);
int descriptor = shm_open("/shmerman",O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
fprintf(stderr,"ERROR with shmctl (%d: %s)\n", (int)(errno), strerror(errno));
fprintf(stderr,"%d", descriptor);
ftruncate(descriptor, integerSize);
fprintf(stderr,"ERROR with shmctl (%d: %s)\n", (int)(errno), strerror(errno));
result = mmap(NULL, integerSize, PROT_WRITE | PROT_READ, MAP_SHARED, descriptor, 0 );
sleep(10);
fprintf(stderr,"SIMDI DEALLOCATE EDIORUM");
sleep(10);
ftruncate(descriptor, 600000);
return 0;
}
This time , I checked the file named shmerman, which was located under /dev/shm and saw that its size was 300000b after created and it jumped to 600000b after 10 seconds..(sleep 10)
Note that: You cant see the shared memory segment allocated by shm_open in ipcs output. You can check the segments from the /dev/shm filesystem.
In 11g , we have memory_target and I believe Oracle uses a similar method, that I just mentioned above, to manage the shared memory . As you know; to be able to use above method, you need to have a /dev/shm.. So /dev/shm is required for using memory_target in Oracle.
Beyond that, I think and read maybe, that Oracle uses /dev/shm to pass segments from SGA(shared memory) to PGA (process memory).. I think it just gives back the shared memory back to OS ,and OS gives it to the processes in case they needed. Giving back the unused memory should be enough for managing the PGA,as is not a limit and it s is not a fixed memory area resides in memory..
So far so good.. On the other hand, 10g Oracle does not use memory_target , naturally it does not use a /dev/shm based memory access..
ipcs output shows that it uses shmget to get the needed shared segments... Also , I have sent a mail to Tanel Poder regarding this topic, and he said by using strace in Oracle startup; shmget call can be seen..
Following was taken in startup process of an Oracle 10gR2 database.
open("/proc/sys/kernel/shmmax", O_RDONLY) = 2 --> It reads the shmmax to obtain the max segment size.
[pid 12584] shmget(2505607756, 6444548096, IPC_CREAT|IPC_EXCL|SHM_HUGETLB|0600) = -1 ENOMEM (Cannot allocate memory) --> It tries the Hugetlbs and can not get them as it s not configured.
[pid 12584] shmget(2505607756, 6444548096, IPC_CREAT|IPC_EXCL|0660) = 557059, then it uses small pages to allocate the 6gb sga , which shmid= 557059
It gets the shared memory using shmget call;
Here is the ipcs command output; shmid in the ouput is the same as it s returned from shmget..(557059)
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xb92f91b4 524290 proddb 660 526385152 27
0x95588a4c 557059 proddb 660 6444548096 12
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
So it s clear Oracle 10g uses shmget to allocate the shared memory segments..
The question is that , how it can resize them?
As we know we can decrease the size of sga on-the-fly using sga_target parameter.
I tested and analyzed it to satisfy my curiosity;
1) sga_target = sga_max_size
First I tested this functionality in a Oracle Database, which has 6 gb sga capacity and configured to use all the 6gb of it. (sga_max_size = 6gb, sga_target=6gb)
There parameter lock_sga=FALSE .. Note that LOCK_SGA locks the entire SGA into physical memory. It is usually advisable to lock the SGA into real (physical) memory, it prevents paging.. I checked this parameter because. It can mislead us..
After the startup of the instance; I see that shared memory segment size is 6gb. So, it s clear that Oracle allocated 6 gb of shared memory (note that sga_target is 6gb too)
Here is the ipcs command output , just after startup;
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 557059 proddb 660 6444548096 16
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Look at the following Oracle process.. It has 6325 of virtual memory.. 6 gb + some mbytes.. So Oracle process is prepared to be is able to access 6 gb memory at the present moment.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12606 proddb 16 0 6325m 1.3g 1.2g S 0.0 7.1 0:15.36 oracle
Output of free command show approx 18007-(17064+227)
free -m
total used free shared buffers cached
Mem: 18049 18007 41 0 227 17064
-/+ buffers/cache: 716 17333
Swap: 8001 0 8000
Lets look at the Shared memory components of Oracle.It has a sga configured to 6 gb.
It has 5301600256 bytes 's of buffer cache. 1056964608 bytes of Shared pool and etc..
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093544 bytes
Variable Size 1124077080 bytes
Database Buffers 5301600256 bytes
Redo Buffers 14680064 bytes
So here is the ipcs ouput just after restart.. Oracle still allocates 6gb Sga.. But this does not mean, that this memory is initialized and taken from physical memory.
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 589827 proddb 660 6444548096 14
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Oracle processes still maps more than 6gb memory.. VIRT column supplies this information.. Virtual memory is a memory map that can be point to physical memory, or a swap disk space, or a memory "to be allocated".
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14231 proddb 16 0 6284m 38m 34m S 0.0 0.2 0:00.06 oracleDEV (LOCAL=NO)
$ free -m
total used free shared buffers cached
Mem: 18049 18016 32 0 229 17048
-/+ buffers/cache: 737 17311
Swap: 8001 0 8000
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093584 bytes
Variable Size 2986348016 bytes
Database Buffers 3439329280 bytes
Redo Buffers 14680064 bytes
As you see above, Oracle allocated 6gb Sga. Buffer cache size is 3.2Gb. , the variable size is 2.78Gb..
It looks like it is same whether we use sga_target = 4gb or sga_target = 6b.. But it is not the same.
Look at Free SGA Memory Available .. It is 2147483648, which is 2gb.
3) Lets reduce the sga_target value from 4gb to 2b of this running instance ..
(sga_max_size=6gb, sga_target = 2gb (reduced from 4gb, without restarting the db)
SQL> alter system set sga_target=2g;
System altered.
ipcs output shows the same; 6gb shared memory segment is stil allocated.
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 589827 proddb 660 6444548096 15
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Top command shows the same, VIRTUAL Memory of a given Oracle process is approx. 6gb.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13611 proddb 16 0 6284m 20m 16m S 0.0 0.1 0:00.03 oracle
Output of free command shows similar amount of free memory..
total used free shared buffers cached
Mem: 18049 18009 40 0 238 17032
-/+ buffers/cache: 738 17310
Swap: 8001 0 8000
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093584 bytes
Variable Size 5133831664 bytes
Database Buffers 1291845632 bytes
Redo Buffers 14680064 bytes
SQL> select * from v$sgainfo;
NAME BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size 2093584 No
Redo Buffers 14680064 No
Buffer Cache Size 1291845632 Yes
Shared Pool Size 771751936 Yes
Large Pool Size 16777216 Yes
Java Pool Size 16777216 Yes
Streams Pool Size 33554432 Yes
Granule Size 16777216 No
Maximum SGA Size 6442450944 No
Startup overhead in Shared Pool 134217728 No
Free SGA Memory Available 4294967296
Not seeing the unused portion of the shared memory in ipcs and top is not an issue. These are tools, so they can be coded that way. No need to investigate..
There parameter lock_sga=FALSE .. Note that LOCK_SGA locks the entire SGA into physical memory. It is usually advisable to lock the SGA into real (physical) memory, it prevents paging.. I checked this parameter because. It can mislead us..
After the startup of the instance; I see that shared memory segment size is 6gb. So, it s clear that Oracle allocated 6 gb of shared memory (note that sga_target is 6gb too)
Here is the ipcs command output , just after startup;
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 557059 proddb 660 6444548096 16
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Look at the following Oracle process.. It has 6325 of virtual memory.. 6 gb + some mbytes.. So Oracle process is prepared to be is able to access 6 gb memory at the present moment.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12606 proddb 16 0 6325m 1.3g 1.2g S 0.0 7.1 0:15.36 oracle
Output of free command show approx 18007-(17064+227)
free -m
total used free shared buffers cached
Mem: 18049 18007 41 0 227 17064
-/+ buffers/cache: 716 17333
Swap: 8001 0 8000
Lets look at the Shared memory components of Oracle.It has a sga configured to 6 gb.
It has 5301600256 bytes 's of buffer cache. 1056964608 bytes of Shared pool and etc..
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093544 bytes
Variable Size 1124077080 bytes
Database Buffers 5301600256 bytes
Redo Buffers 14680064 bytes
SQL> select * from v$sgainfo;
NAME BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size 2093544 No
Redo Buffers 14680064 No
Buffer Cache Size 5301600256 Yes
Shared Pool Size 1056964608 Yes
Large Pool Size 16777216 Yes
Java Pool Size 16777216 Yes
Streams Pool Size 33554432 Yes
Granule Size 16777216 No
Maximum SGA Size 6442450944 No
Startup overhead in Shared Pool 167772160 No
Free SGA Memory Available 0
So everything is just like expected, here.. we use all the sga , and Free SGA Memory Available =0
2) sga_target < sga_max_size
Next I tested this functionality in a Oracle Database, which has 6 gb sga capacity but configured to use 4gb of it. (sga_max_size = 6gb, sga_target=4gb)So here is the ipcs ouput just after restart.. Oracle still allocates 6gb Sga.. But this does not mean, that this memory is initialized and taken from physical memory.
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 589827 proddb 660 6444548096 14
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Oracle processes still maps more than 6gb memory.. VIRT column supplies this information.. Virtual memory is a memory map that can be point to physical memory, or a swap disk space, or a memory "to be allocated".
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14231 proddb 16 0 6284m 38m 34m S 0.0 0.2 0:00.06 oracleDEV (LOCAL=NO)
$ free -m
total used free shared buffers cached
Mem: 18049 18016 32 0 229 17048
-/+ buffers/cache: 737 17311
Swap: 8001 0 8000
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093584 bytes
Variable Size 2986348016 bytes
Database Buffers 3439329280 bytes
Redo Buffers 14680064 bytes
SQL> select * from v$sgainfo;
NAME BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size 2093584 No
Redo Buffers 14680064 No
Buffer Cache Size 3439329280 Yes
Shared Pool Size 771751936 Yes
Large Pool Size 16777216 Yes
Java Pool Size 16777216 Yes
Streams Pool Size 33554432 Yes
Granule Size 16777216 No
Maximum SGA Size 6442450944 No
Startup overhead in Shared Pool 134217728 No
Free SGA Memory Available 2147483648
As you see above, Oracle allocated 6gb Sga. Buffer cache size is 3.2Gb. , the variable size is 2.78Gb..
It looks like it is same whether we use sga_target = 4gb or sga_target = 6b.. But it is not the same.
Look at Free SGA Memory Available .. It is 2147483648, which is 2gb.
3) Lets reduce the sga_target value from 4gb to 2b of this running instance ..
(sga_max_size=6gb, sga_target = 2gb (reduced from 4gb, without restarting the db)
SQL> alter system set sga_target=2g;
System altered.
ipcs output shows the same; 6gb shared memory segment is stil allocated.
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x95588a4c 589827 proddb 660 6444548096 15
0x00000000 360452 proddb 644 151552 2 dest
0x00000000 393221 proddb 644 122880 2 dest
0x00000000 425990 proddb 644 790528 2 dest
Top command shows the same, VIRTUAL Memory of a given Oracle process is approx. 6gb.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13611 proddb 16 0 6284m 20m 16m S 0.0 0.1 0:00.03 oracle
Output of free command shows similar amount of free memory..
total used free shared buffers cached
Mem: 18049 18009 40 0 238 17032
-/+ buffers/cache: 738 17310
Swap: 8001 0 8000
SQL> show sga
Total System Global Area 6442450944 bytes
Fixed Size 2093584 bytes
Variable Size 5133831664 bytes
Database Buffers 1291845632 bytes
Redo Buffers 14680064 bytes
SQL> select * from v$sgainfo;
NAME BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size 2093584 No
Redo Buffers 14680064 No
Buffer Cache Size 1291845632 Yes
Shared Pool Size 771751936 Yes
Large Pool Size 16777216 Yes
Java Pool Size 16777216 Yes
Streams Pool Size 33554432 Yes
Granule Size 16777216 No
Maximum SGA Size 6442450944 No
Startup overhead in Shared Pool 134217728 No
Free SGA Memory Available 4294967296
As we see; ipcs ,top -p, free -m and oracle's sga outputs are similar(they point to 6gb shared memory), but Free SGA Memory Available showed in v$sqainfo display 4gb free, as expected..
Not seeing the unused portion of the shared memory in ipcs and top is not an issue. These are tools, so they can be coded that way. No need to investigate..
But, following are the questions;
How can Oracle make use of the advantages brought by sga_target? Actually, how does OS threat these allocated but not used shared memory blocks..
I will try to answer these questions in a few days.
How can Oracle make use of the advantages brought by sga_target? Actually, how does OS threat these allocated but not used shared memory blocks..
I will try to answer these questions in a few days.
No comments :
Post a Comment
If you will ask a question, please don't comment here..
For your questions, please create an issue into my forum.
Forum Link: http://ermanarslan.blogspot.com.tr/p/forum.html
Register and create an issue in the related category.
I will support you from there.