onmode -F

The IBM Informix utility onmode -F has the following claims made about it in the IBM documentation:

When you execute onmode -F, the memory manager examines each memory pool for unused memory. When the memory manager locates blocks of unused memory, it immediately frees the memory. After the memory manager checks each memory pool, it begins checking memory segments and frees any that the database server no longer needs.

and:

To confirm that onmode freed unused memory, check your message log. If the memory manager frees one or more segments, it displays a message that indicates how many segments and bytes of memory were freed.

In my experience though running onmode -F rarely seems to do anything and I look in the message log in vain.

18:51:56 Attempting to free unused operating system segments. This
operation may take several minutes.

And it’s followed by nothing. In fact I would go as far as to say I’ve rarely seen it work. Why is this? One reason seems to be if the segment is used to store information about database locks.

On an instance configured with a small amount of shared memory and a low number of available locks we can force the engine to dynamically allocate more locks, thus requiring a new shared memory segment using a simple procedure like the below:

create procedure test()
returning int;

define count int;
define num_rows int;

create table onmode_f_test (
tabname varchar(254),
owner varchar(254)
) lock mode row;

for count=1 to 1000
insert into onmode_f_test select tabname, owner from systables;
end for;

select count(*) into num_rows from onmode_f_test;

begin work;
update onmode_f_test set owner='fred';
commit;

drop table onmode_f_test;

return(num_rows);

end procedure;

execute procedure test();
drop procedure test();

On my low memory instance we can easily then go from this situation:

informix@ids1150srvr[demo_on]:/opt/IBM/informix$ onstat -g seg

IBM Informix Dynamic Server Version 11.50.UC4DE -- On-Line -- Up 00:00:13 -- 22556 Kbytes

Segment Summary:
id key addr size ovhd class blkused blkfree
1146880 52564801 44000000 5689344 256356 R 1385 4
1179649 52564802 4456d000 17408000 103088 V 4206 44
Total: - - 23097344 - - 5591 48

(* segment locked in memory)

to this:

informix@ids1150srvr[demo_on]:~$ onstat -g seg

IBM Informix Dynamic Server Version 11.50.UC4DE -- On-Line -- Up 00:00:35 -- 30748 Kbytes

Segment Summary:
id key addr size ovhd class blkused blkfree
1146880 52564801 44000000 5689344 256356 R 1385 4
1179649 52564802 4456d000 17408000 103088 V 4228 22
1212430 52564803 45607000 8388608 50192 V 1664 384
Total: - - 31485952 - - 7277 410

(* segment locked in memory)

Note that an extra virtual segment has been created (there are two segments of class V).

And in the online log we see:

19:24:26 dynamically allocated 20000 locks

Now of course I have contrived this situation to force the instance to run out of locks in this way but this is a realistic scenario on a stretched production box running a large or badly written query. It happened to an instance I maintain with 12 million locks configured and because the system was tuned to use all the available memory, these extra shared segments forced the system to page excessively.

So after my stored procedure has finished executing and so I might expect that with no-one connected to the system I could delete the new shared memory segment with onmode -F. Well it won’t go.

Why is this? The reason is that the shared memory area for the extra locks is in this segment. This simple query will show us that this is the case:

select lk_id, hex(lk_addr) from sysmaster.syslocktab;

The result is as follows:

lk_id (expression)

0 0x00000000440fddc4
1 0x00000000440fde24
2 0x00000000440fde84
20195 0x0000000045713938

If you compare this with the output from onstat -g seg from above you’ll see that lock ID 20195 is in the second virtual segment:

Segment Summary:
id key addr size ovhd class blkused blkfree
1146880 52564801 44000000 5689344 256356 R 1385 4
1179649 52564802 4456d000 17408000 103088 V 4228 22
1212430 52564803 45607000 8388608 50192 V 1664 384
Total: - - 31485952 - - 7277 410

This one has baffled me for a while and it was satisfying to find a solution to this. There are other system tables you can look in to see other shared memory segments. syspoollst shows the memory pools used by user sessions, for example.

Advertisements