Archive for February, 2009
Create Table Creating Dirty Buffers….
Posted by Aman Sharma in internals on February 17, 2009
I always thought that the creation of table is a mere data dictionary update. I mean to say that the data dictionary , dba_tables, OBJ$ and other similar ones would get updated when we create a table. The logic was that its just a definition so where else it would be going? Its correct too that its just a definition but still for couple of things, Oracle does access DataBuffer Cache too when it creates a table and (here is what I didnt even think to see) not just accesses it but also makes couple of its block dirty too. Doesn’t make a sense,well ok let the numbers,bits, flags speak then. Have a look,
- SQL*Plus: Release 11.1.0.6.0 - Production on Fri Aug 22 00:24:26 2008
- Copyright (c) 1982, 2007, Oracle. All rights reserved.
- Enter password:
- Connected to:
- Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
- With the Partitioning, Oracle Label Security, OLAP, Data Mining,
- Oracle Database Vault and Real Application Testing options
- SQL> create table t (a number);
- Table created.
- SQL> select object_id ,object_name from user_objects where object_name=‘T’;
- OBJECT_ID OBJECT_NAME
- ———- ———-
- 72217 T
- SQL> SELECT b.block#,b.class#,b.status, object_name, object_type, dirty “Dirty” FROM v$bh b,
- 2 dba_objects o WHERE b.objd = o.data_object_id AND o.owner = ‘AMAN’ and object_name=‘T’;
- BLOCK# CLASS# STATUS OBJECT_NAME OBJECT_TYPE D
- ———- ———- ———- ——————– ——————- -
- 3746 9 xcur T TABLE Y
- 3745 8 xcur T TABLE Y
- 3747 4 xcur T TABLE Y
- SQL>
The buffers from the table T are marked Dirty and are accessed in the XCUR mode which means the blocks are accessed in the Exclusive Current mode and is representing that these blocks are going to be modified. The description of the buffer status which is shown from V$BH(or X$BH.status) from 11gr1 docs is given here,
STATUS |
VARCHAR2(6) |
Status of the buffer:
|
Here is the link for the same in docs.http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/dynviews_1059.htm#REFRN30029
A much better description of the same is mentioned in the 9iR2 docs,in the RAC guide. The link is mentioned below and also the description,
http://download.oracle.com/docs/cd/B10501_01/rac.920/a96597/pslkgdtl.htm#19780
Block Access Modes and Buffer States
An additional concurrency control concept is the buffer state which is the state of a buffer in the local cache of an instance. The buffer state of a block relates to the access mode of the block. For example, if a buffer state is exclusive current (XCUR), an instance owns the resource in exclusive mode.
To see a buffer’s state, query the STATUS column of the V$BH dynamic performance view. The V$BH view provides information about the block access mode and their buffer state names as follows:
- With a block access mode of
NULLthe buffer state name isCR–An instance can perform a consistent read of the block. That is, if the instance holds an older version of the data. - With a block access mode of
Sthe buffer state name isSCUR–An instance has shared access to the block and can only perform reads. - With a block access mode of
Xthe buffer state name isXCUR–An instance has exclusive access to the block and can modify it. - With a block access mode of
NULLthe buffer state name isPI–An instance has made changes to the block but retains copies of it as past images to record its state before changes.
Only the SCUR and PI buffer states are Real Application Clusters-specific. There can be only one copy of any one block buffered in the XCUR state in the cluster database at any time. To perform modifications on a block, a process must assign an XCUR buffer state to the buffer containing the data block.
For example, if another instance requests read access to the most current version of the same block, then Oracle changes the access mode from exclusive to shared, sends a current read version of the block to the requesting instance, and keeps a PI buffer if the buffer contained a dirty block.
At this point, the first instance has the current block and the requesting instance also has the current block in shared mode. Therefore, the role of the resource becomes global. There can be multiple shared current (SCUR) versions of this block cached throughout the cluster database at any time.
So the blocks are meant for the modification and hence they are marked dirty after being modified. The same is confirmed from the query written by Jonathan Lewis,
- SQL> select
- decode(bitand(flag,power(2,00)),0,‘No’,‘Yes’ ) buffer_dirty,
- decode(bitand(flag,power(2,01)),0,‘No’,‘Yes’ ) about_to_modify,
- decode(bitand(flag,power(2,02)),0,‘No’,‘Yes’ ) mod_started,
- decode(bitand(flag,power(2,03)),0,‘No’,‘Yes’ ) block_has_been_logged,
- decode(bitand(flag,power(2,04)),0,‘No’,‘Yes’ ) temp_data,
- decode(bitand(flag,power(2,05)),0,‘No’,‘Yes’ ) being_written,
- decode(bitand(flag,power(2,06)),0,‘No’,‘Yes’ ) waiting_for_write,
- decode(bitand(flag,power(2,07)),0,‘No’,‘Yes’ ) checkpoint_wanted,
- decode(bitand(flag,power(2,08)),0,‘No’,‘Yes’ ) recovery_reading,
- decode(bitand(flag,power(2,09)),0,‘No’,‘Yes’ ) unlink_from_lock,
- decode(bitand(flag,power(2,10)),0,‘No’,‘Yes’ ) down_grade_lock,
- decode(bitand(flag,power(2,11)),0,‘No’,‘Yes’ ) cross_instance_write,
- decode(bitand(flag,power(2,12)),0,‘No’,‘Yes’ ) reading_as_CR,
- decode(bitand(flag,power(2,13)),0,‘No’,‘Yes’ ) gotten_in_current_mode,
- decode(bitand(flag,power(2,14)),0,‘No’,‘Yes’ ) stale,
- decode(bitand(flag,power(2,15)),0,‘No’,‘Yes’ ) deferred_ping,
- decode(bitand(flag,power(2,16)),0,‘No’,‘Yes’ ) direct_access,
- decode(bitand(flag,power(2,17)),0,‘No’,‘Yes’ ) moved_to_lru_tail,
- decode(bitand(flag,power(2,18)),0,‘No’,‘Yes’ ) ignore_redo,
- decode(bitand(flag,power(2,19)),0,‘No’,‘Yes’ ) only_sequential_access,
- decode(bitand(flag,power(2,20)),0,‘No’,‘Yes’ ) unused_0×100000,
- decode(bitand(flag,power(2,21)),0,‘No’,‘Yes’ ) re_write_needed,
- decode(bitand(flag,power(2,22)),0,‘No’,‘Yes’ ) flushed,
- decode(bitand(flag,power(2,23)),0,‘No’,‘Yes’ ) resilvered_already,
- decode(bitand(flag,power(2,24)),0,‘No’,‘Yes’ ) ckpt_writing,
- decode(bitand(flag,power(2,25)),0,‘No’,‘Yes’ ) redo_since_read,
- decode(bitand(flag,power(2,26)),0,‘No’,‘Yes’ ) unused_0×4000000,
- decode(bitand(flag,power(2,27)),0,‘No’,‘Yes’ ) unused_0×8000000,
- decode(bitand(flag,power(2,28)),0,‘No’,‘Yes’ ) unused_0×10000000,
- decode(bitand(flag,power(2,29)),0,‘No’,‘Yes’ ) unused_0×20000000,
- decode(bitand(flag,power(2,30)),0,‘No’,‘Yes’ ) unused_0×40000000,
- decode(bitand(flag,power(2,31)),0,‘No’,‘Yes’ ) unused_0×80000000
- from x$bh where obj=72217;
- BUF ABO MOD BLO TEM BEI WAI CHE REC UNL DOW CRO REA GOT STA DEF DIR MOV IGN ONL UNU RE_ FLU RES CKP RED UNU UNU UNU UNU UNU UNU
- — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
- Yes No No No No No No No No No No No No No No No No No No No No No No No No Yes No No No No No No
- Yes No No No No No No No No No No No No No No No No No No No No No No No No Yes No No No No No No
- Yes No No No No No No No No No No No No No No No No No No No No No No No No Yes No No No No No No
So indeed the buffers are marked are as dirty only. But the buffers are supposed to be marked dirty when they are changed and with the create table,what’s going on which has made them change. Each buffer belongs to a particular classLets try to find out the class description of these buffers using their numbers.The block classes are described here*,
| Block Class | Description |
| 1 | Data block |
| 2 | Sort block |
| 3 | Save undo block |
| 4 | Segment header |
| 5 | Save undo header |
| 6 | Free list |
| 7 | Extent map |
| 8 | 1st level bitmap block |
| 9 | 2nd level bitmap block |
| 10 | 3rd level bitmap block |
| 11 | Bitmap block |
| 12 | Bitmap index block |
| 13 | File header block |
| 14 | Unused |
| 15 | System undo block |
| 16 | System undo block |
| 17 | Undo header |
| 18 | Undo block |
So according to the result that we have got, the blocks belong to the classes 4,8,9 and these numbers represent the classes(in the same order ),Header Block,1st level Bitmap Block,2nd Level Bitmap Block.
When oracle creates a table, it has to allocate a segment header block. This is done by picking up a block from a cache,formatting it,writing into it the new description of the data segment.As it is written so it is marked dirty and subsequently is written to the datafile.
The Automatic Segment Space Management allocates 3 levels of the blocks for example, Level1 , Level2 , Level3. The level 3 is the bitmap header block which resides in the segment header. This is linked to the Level 2 block. This block is used to search Level 1 which is always the first block in the extent. Level 1 marks the blocks for their respective status. So it appears , Oracle does the same what it does for the Segment header block to the Bitmap Blocks i.e. acquires two blocks from the cache , marks as Bitmap blocks, writes into them and marks them dirty. So this is the reason that we get the blocks marked as dirty even when we have not done anything by ourselves to change them. For me it was a new concept as I was not aware about it before. I would still try to dig upon more and will try to post more as and when I shall find it out. Heartiest thanks to Jonathan Lewis for helping me to understand it.
References,
A New Learning, IMU & Private Redo Strand….
Posted by Aman Sharma in internals on February 11, 2009
There are very few things that I know but there are tons of things which I don’t know. I came across one more such thing like this few days ago when this question (http://forums.oracle.com/forums/thread.jspa?messageID=2713561�) came over OTN. Interestingly, what the OP mentioned was indeed true and I was not having a clue what’s going on. Like most of the times, JL had an answer to the puzzle and he gave a lead. This blog post is not about any “new” invention that I have done. Its merely a collection of my understanding about a new mechanism in >10g SGAs. So with this note ,let’s get the party started.
Dirty Buffers & Redo Log Buffer
In Oracle buffer cache, buffers stay in multiple states. When a buffer is not changed and is just available for use, it’s a clean buffer. When the buffer encounters a change, the buffer status is marked as Dirty buffer. This status is used by Oracle to provide read-consistancy for the other users who would access the same buffer but when the transaction is alive. In simple terms, a dirty buffer is that one who got an image in it which is not the one when it was brought into the cache. Oracle maintains for this dirty buffer, CR(consistent read) buffers aka snapshot blocks which provide read conistancy for the others.
The change vectors for this buffer are also logged in the redo log buffer before they get applied to the actual buffers(write ahead logging) , using which Oracle maintains this assurance that no matter what, if we have the data in the log buffer, its safe. The data in the log buffer is written by LGWR to the redo log files. Once there, its permanently saved and hence protected against any crash.
In order to log changes in the log buffer, oracle typically follows this process
1) A calculation is done that how much space would be needed in the log buffer.
2) Server process acquires Redo Copy Latch. This is used for making the announcement that some redo will be copied into the log buffer.
3) Acquires Redo Allocation Latch. This is the actual latch which will allocate the space in the log buffer.
4) Redo Allocation Latch is released after the space is acquired in the log buffer.
5) Redo copy latch is used to copy the redo change vectors in the log buffers.
6) Redo copy latch is released.
After the copy is copy is complete and applying them over the buffers in the buffer cache, depending upon various conditions, LGWR may start writing the contents into the log files. How many latches we have got have at the moment for our database can be seen from V$latch_childeren. Here is an output from my 11gr1 machine.
1 select latch#,child#,name from V$latch_children
2* where name like ‘%redo%’ order by 1,2
SQL> /
LATCH# CHILD# NAME
———- ———- —————————————————————-
169 1 redo copy
169 2 redo copy
169 3 redo copy
169 4 redo copy
170 1 redo allocation
170 2 redo allocation
170 3 redo allocation
170 4 redo allocation
170 5 redo allocation
170 6 redo allocation
170 7 redo allocation
170 8 redo allocation
170 9 redo allocation
170 10 redo allocation
170 11 redo allocation
170 12 redo allocation
170 13 redo allocation
170 14 redo allocation
170 15 redo allocation
170 16 redo allocation
170 17 redo allocation
170 18 redo allocation
170 19 redo allocation
170 20 redo allocation
24 rows selected.
With heavy processing, lots of redo being generated, there may be a contention over the redo allocation latches. So for this purpose, there was a parameter Log_parallelism( http://download.oracle.com/docs/cd/B10501_01/server.920/a96536/ch1105.htm#REFRN10099) in 9i which could be used to make the redo generation go more faster. This would separate the log buffer into further small buffers. This parameter is only till 9i and from 10.1 onwards its deprecated(http://download.oracle.com/docs/cd/B28359_01/server.111/b28300/changes.htm#UPGRD12575) as in 10g, the mechanism is changed ( and is the actual topic of this post) which handles the excessive redo workload.
So the moral of the story so far comes up is that when we change some thing in the buffer cache, the change is protected in the log buffer. To do this two latches are majorly used. The changes in the log buffer are protected in the physical log files by LGWR.
You must be thinking that that is this the replica of docs or what? Well certainly, it’s the basics and I thought before I forget all this, I must write it down and this talks about the terms which will be coming up a little later in the post. So chill J. Told you its not any new invention but collection
.
What’s Wrong With All This
Well actually nothing much. This is some this which is happening since the inception of Oracle I believe. Some things came and go but in nutshell things remained the same. This allocation of latches and other stuff did prove to be fine but as they all good things come to an end, this also needed some modifications. As with the workloads being more heavy and with much bigger databases and higher transaction rates, it becomes too tough to manage the redo allocations using latches. Clearly for the reasons that are well documented in PT guide that with lots of redo, the latches required to copy the redo data in the log buffer come under contention and so does the LGWR process too. There is a workaround to invoke multiple slaves for LGWR for heavy systems but that too is not some thing which is not recommended as long as not fully benchmarked. Surely there are tons of guidelines that are there for users in order to make transactions small, have a good media where redo can stay and so on but they can be applied to a certain level. So there was a need for things to be modified from the grass root level and that’s what happened in 10g(10.1) onwards.
A Strange Output
With the Dirty Buffers discussion given above, you must be clear about the idea about them. So here is small table creation and modification and we would see some dirty buffers getting created,
SQL> select * from V$version;
BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 – Production
PL/SQL Release 11.1.0.6.0 – Production
CORE 11.1.0.6.0 Production
TNS for 32-bit Windows: Version 11.1.0.6.0 – Production
NLSRTL Version 11.1.0.6.0 – Production
SQL> alter system flush buffer_cache;
System altered.
SQL> create table t(a number)
2 /
Table created.
SQL> SELECT b.status, object_name, object_type, dirty “Dirty” FROM v$bh b, dba_objects o
2 WHERE b.objd = o.data_object_id AND o.owner = ‘AMAN’ and object_name=’T’;
STATUS OBJECT_NAME
———- ———————————————————————————–
———
OBJECT_TYPE D
——————- -
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
SQL> insert into t values(1);
1 row created.
SQL> SELECT b.status, object_name, object_type, dirty “Dirty” FROM v$bh b, dba_objects o
2 WHERE b.objd = o.data_object_id AND o.owner = ‘AMAN’ and object_name=’T’;
STATUS OBJECT_NAME
———- ———————————————————————————–
———
OBJECT_TYPE D
——————- -
xcur T
TABLE Y
xcur T
TABLE N
xcur T
TABLE N
xcur T
TABLE Y
xcur T
TABLE N
xcur T
TABLE Y
xcur T
TABLE N
xcur T
TABLE N
8 rows selected.
SQL>
SQL> commit;
Commit complete.
SQL> SELECT b.status, object_name, object_type, dirty “Dirty” FROM v$bh b, dba_objects o
2 WHERE b.objd = o.data_object_id AND o.owner = ‘AMAN’ and object_name=’T’;
STATUS OBJECT_NAME
———- —————————————————————————–
———
OBJECT_TYPE D
——————- -
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
xcur T
TABLE Y
8 rows selected.
SQL>
Well if you have seen the output with a little care, you must have seen that even when we have given the dmp(insert in this case) there were no buffers which were marked dirty. Oracle did acquire some buffers to keep our changes but they were not marked dirty. But when we issued commit, all the buffers were marked dirty. Why so?
The New SGA Of IMU/ Private Redo Strands
Due to the reasons mentioned above for the allocation and redo latch contentions, from 10.1 onwards, Oracle has introduced private redo allocation areas and In memory Undo.
IMU(In Memory Undo)
With the same reason that Oracle needs to protect redo, it also has to protect Undo to make sure that the block’s old contents are also saved. This would require an access to the blocks and than later on change the transaction table to make the changes logged. The transaction records can be seen from V$transaction. In order to access undo segment header blocks directly, we can also check X$KTUXE and for the base table of V$transaction, X$KTCXB can be used. From oracle 10g onwards, Oracle does use the Undo blocks but makes them available in private memory areas which are specifically created in the Shared Pool. Each pool is containing Undo data of a transaction. Undo data is updated into the segment header but not into the undo blocks. For maintaining them, in the shared pool , memory areas are configured which are used to protect the undo that is coming up. These are controlled by two parameters _in_memory_undo and _imu_pools. Both can be seen from the base tables x$ksppi and x$ksppcv2
SQL> l
1 select KSPFTCTXDVL,kspftctxdf,ksppinm
2 from x$ksppcv2 a,x$ksppi b
3* where a.indx=b.indx and b.ksppinm like ‘%imu%’
SQL> column KSPFTCTXDVL format a10
SQL> /
KSPFTCTXDV KSPFTC KSPPINM
———- —— —————————————————
2 TRUE _simulator_upper_bound_multiple
16 TRUE _simulator_pin_inval_maxcnt
10240 TRUE _simulator_lru_rebalance_thresh
5 TRUE _simulator_lru_rebalance_sizthr
8192 TRUE _simulator_bucket_mindelta
8 TRUE _simulator_lru_scan_count
10 TRUE _simulator_internal_bound
1024 TRUE _simulator_reserved_obj_count
4096 TRUE _simulator_reserved_heap_count
2 TRUE _simulator_sampling_factor
0 TRUE _simulate_mem_transfer
0 TRUE _db_writer_flush_imu
0 TRUE _minimum_giga_scn
1800 TRUE _log_simultaneous_copies
d:\oracle\ FALSE _allow_error_simulation
flash_reco
very_area
SLFLUSH TRUE _gc_policy_minimum
FALSE TRUE _gc_maximum_bids
TRUE TRUE _minimum_db_flashback_retention
600 TRUE _recursive_imu_transactions
TRUE TRUE _smu_error_simulation_site
TRUE TRUE _smu_error_simulation_type
0 TRUE _imu_pools
10 TRUE _minimum_blocks_to_shrink
TRUE TRUE _minimum_extents_to_shrink
RUN_TIME TRUE _plsql_minimum_cache_hit_percent
25 rows selected.
And
SQL> l
1 select KSPFTCTXDVL,kspftctxdf,KSPFTCTXVL,KSPFTCTXIS,ksppinm
2 from x$ksppcv2 a,x$ksppi b
3* where a.indx=b.indx and b.ksppinm like ‘%undo%’
SQL> /
KSPFTCTXDV KSPFTC KSPFTCTXVL KSPFTC KSPPINM
———- —— ———- —— ——————–
FALSE TRUE FALSE FALSE _gc_undo_affinity
AUTO TRUE AUTO FALSE _gc_dissolve_undo_af
finity
TRUE TRUE TRUE FALSE _gc_initiate_undo_af
finity
0 TRUE 0 FALSE _gc_undo_block_disk_
reads
TRUE FALSE _undo_block_compress
ion
TRUE FALSE undo_management
TRUE FALSE undo_tablespace
100 TRUE 100 FALSE _collect_undo_stats
0 TRUE 0 FALSE _undo_debug_mode
0 TRUE 0 FALSE _verify_undo_quota
TRUE FALSE _in_memory_undo
FALSE TRUE FALSE FALSE _undo_autotune
FALSE TRUE FALSE FALSE undo_retention
0 TRUE 0 FALSE _undo_debug_usage
0 TRUE 0 FALSE _smon_undo_seg_resca
n_limit
0 TRUE 0 FALSE _optimizer_undo_cost
_change
TRUE TRUE TRUE FALSE _optimizer_undo_chan
ges
17 rows selected.
Each pool is maintained by a latch and that is called “in memory undo latch”. They can be seen from V$latch_children
SQL> select name from V$latch_children where name like ‘%undo%’;
NAME
—————————————————————-
undo global data
undo global data
undo global data
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
In memory undo latch
21 rows selected.
We can see that in the shared pool, regarding Undo,there are several structures available.
SQL> select pool,name from V$sgastat where pool=’shared pool’ and lower(name) like ‘%undo%’;
POOL NAME
———— ————————–
shared pool UNDO INFO SEGMENTED ARRAY
KCB undo bitvec
Undo Meta Data
Auto tune undo info
UNDO INFO
KTI-UNDO
UNDO INFO HASH
UNDO STAT INFO
The IMU pools are allocated in the shared pool. The data that we change gets copied to these pools from a latch called In memory Undo latch. We can see it here from V$latch,
SQL> select name from V$latch where name like ‘%undo%’;
NAME
—————————————————————-
undo global data
corrupted undo seg lock
In memory undo latch
When we modify the data, oracle doesn’t apply the data to the data blocks immediately but It allocates the data in the IMU pools in the shared pool with the help of this IMU latch. This mechanism avoids the pinning of the Undo segment header block and also to the undo data blocks which are otherwise used immediately when the transaction starts. Now they are only used when the transaction commits. The data is in the pool and from there only it gets copied to the buffer cache. As each pool is assigned to one transaction and is maintained by an individual latch, the mechanism works well to reduce the contention. I am still not clear that with a very very heavy OLTP environment, what would happen? Are the pools increased at that time or not, or some thing else happens, I am not sure.
The IMU pools are also described in the X$ktifp. The size of the pools are 65kb and can be seen as follows,
SQL> select ktifpno,ktifppsi from x$ktifp;
KTIFPNO KTIFPPSI
———- ———-
0 65535
1 65535
2 65535
3 65535
4 65535
5 65535
6 65535
7 65535
8 65535
9 65535
10 65535
KTIFPNO KTIFPPSI
———- ———-
11 65535
12 65535
13 65535
14 65535
15 65535
16 65535
17 65535
18 rows selected.
So there are 18 pools allocated and are of 65kb each in size. This undo data is “flushed” to the undo segments when the pools are full. This write happens in the batch format. There are events when the data in the IMU pools gets flushed. These events are mentioned in the base table x$ktiff. We can see the reasons here,
SQL> l
1 select KTIFFCAT, KTIFFFLC
2* from x$ktiff
SQL> /
KTIFFCAT KTIFFFLC
—————————————- ———-
Undo pool overflow flushes 1
Stack cv flushes 9
Multi-block undo flushes 0
Max. chgs flushes 2
NTP flushes 0
Contention flushes 9
Redo pool overflow flushes 0
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 335
Commit flushes 1570
Recursive txn flushes 2
Redo only CR flushes 0
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 21
Presumed commit violation 0
Securefile direct-write lob update flush 0
es
19 rows selected.
We can see with simple DML that data is being changed and IMU is being flushed.
In session 1, I made a table,
C:\Documents and Settings\Aman>sqlplus / as sysdba
SQL*Plus: Release 11.1.0.6.0 – Production on Sat Aug 30 11:42:21 2008
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 – Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining,
Oracle Database Vault and Real Application Testing options
SQL> create table a as select * from dba_objects;
Table created.
SQL>
And in session 2(the same session from where we saw the events),
SQL> /
KTIFFCAT KTIFFFLC
—————————————- ———-
Undo pool overflow flushes 1
Stack cv flushes 9
Multi-block undo flushes 0
Max. chgs flushes 2
NTP flushes 0
Contention flushes 9
Redo pool overflow flushes 0
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 338
Commit flushes 1592
Recursive txn flushes 2
Redo only CR flushes 0
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 21
Presumed commit violation 0
Securefile direct-write lob update flush 0
es
19 rows selected.
And in session 1,
SQL> select n.name, s.value from v$statname n, v$sesstat s
2 where n.statistic# = s.statistic#
3 and s.sid = (select sid from v$mystat where rownum = 1)
4 and n.name in (’IMU Flushes’,’IMU commits’);
NAME VALUE
—————————————————————- ———-
IMU commits 0
IMU Flushes 0
SQL>
We do some change in the data in session 1,
SQL> insert into a select * from a;
68864 rows created.
SQL> select n.name, s.value from v$statname n, v$sesstat s
2 where n.statistic# = s.statistic#
3 and s.sid = (select sid from v$mystat where rownum = 1)
4 and n.name in (’IMU Flushes’,’IMU commits’);
NAME VALUE
—————————————————————- ———-
IMU commits 0
IMU Flushes 1
And we have got a flush happened as the data generated is too much big. Lets see in session 2,
SQL> /
KTIFFCAT KTIFFFLC
—————————————- ———-
Undo pool overflow flushes 1
Stack cv flushes 9
Multi-block undo flushes 0
Max. chgs flushes 2
NTP flushes 0
Contention flushes 9
Redo pool overflow flushes 1
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 353
Commit flushes 1654
Recursive txn flushes 2
Redo only CR flushes 0
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 21
Presumed commit violation 0
Securefile direct-write lob update flush 0
es
19 rows selected.
After some more changes in session 1,
SQL> insert into a select * from a;
137728 rows created.
SQL> where n.statistic# = s.statistic#
SP2-0734: unknown command beginning “where n.st…” – rest of line ignored.
SQL> select n.name, s.value from v$statname n, v$sesstat s
2 where n.statistic# = s.statistic#
3 and s.sid = (select sid from v$mystat where rownum = 1)
4 and n.name in (’IMU Flushes’,’IMU commits’);
NAME VALUE
—————————————————————- ———-
IMU commits 0
IMU Flushes 1
SQL> commit;
Commit complete.
SQL> select n.name, s.value from v$statname n, v$sesstat s
2 where n.statistic# = s.statistic#
3 and s.sid = (select sid from v$mystat where rownum = 1)
4 and n.name in (’IMU Flushes’,’IMU commits’);
NAME VALUE
—————————————————————- ———-
IMU commits 0
IMU Flushes 1
SQL>
We see again session 1,
SQL> /
KTIFFCAT KTIFFFLC
—————————————- ———-
Undo pool overflow flushes 1
Stack cv flushes 9
Multi-block undo flushes 0
Max. chgs flushes 2
NTP flushes 0
Contention flushes 10
Redo pool overflow flushes 1
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 359
Commit flushes 1688
Recursive txn flushes 2
Redo only CR flushes 0
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 21
Presumed commit violation 0
Securefile direct-write lob update flush 0
es
19 rows selected.
SQL>
This is worth to mention that the same kind of mechanism was introduced by Oracle earlier with the help of Discrete Transaction Management,http://download.oracle.com/docs/cd/B10501_01/server.920/a96524/c17trans.htm#421
But this didn’t work out too well as the DTM used to pin the data blocks during the transaction. When the transaction used to get committed than the data was written to the redo logs. In private redo, no pinning of the data blocks is done. Hence they are much better than DTM. DTM is obsolete now.
Private Redo Strands( Private Redo )
Earlier there was a single redo allocation latch available for the entire log buffer. This was a major contention point as till the time one won’t be able to pin the latch, he wont be able to write his changed redo vectors in the log buffer. From 10.1 onwards, the log buffer is broken in to smaller sub-buffers called Private Redo Strands(shown in the x$kcrfstrand). These are also allocated in the shared pool. These all are written by redo allocation latches. There are allocation latches now for each private strand. The data when changed now, doesn’t contend to go into the log buffer as like before but goes into the private redo strands and from there, it goes into the log buffer when the buffer pools become full or when the transaction is committed. We can see the private strands shown in the shared pool from the V$sgastat
SQL> select name,pool from V$sgastat
2 where name like ‘%private%’;
NAME POOL
————————– ————
private strands shared pool
KCB private handles shared pool
At log file switch , when the data is still is in the Private redo strands, lgwr may wait to get the flush done by DBWR. Hence the event, log file switch (private strand flush incomplete) may occur. See the doc note for it,
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/waitevents003.htm#sthref3117
This is controlled by the parameter _log_parallelism which is a dynamic and hidden parameter in 10g. The value depends on the cpu_count parameter. Oracle starts with 2 strands.
The benefit of private redo strand is also for the same reason that this would make the LGWR less busy and also the contention over the redo allocation latches will decrease.
Reference:
www.tanelpoder.com/files/Oracle_Performance_Scalability_10g_11g.pdf
http://www.fortunecity.com/skyscraper/oracle/699/orahtml/hayden/discrete.html
Can You Hear The Tweet….
Posted by Aman Sharma in genernal on February 5, 2009
I have just configured a plugin to push the blog posts to come over Twitter! So if you are seeing this as a tweet , that plugin is plugged in correctly
.
Want To Be A Good DBA?
Posted by Aman Sharma in genernal on February 4, 2009
Lot of times this question is asked that how one can be a good dba( I am looking forward to become one myself) and the answers are standard only like, train yourself constantly, look for new technologies and test/play with them, document your stuff, be proactive and so on. The answers depend upon from person to person and the quality of them over the experience of the person. Here it doesn’t matter you are a dba of Oracle Database or DB2 or MSSQL or whatever. Pythian’s Keith talks about the same here.
http://www.pythian.com/blogs/1169/what-makes-a-good-dba
Well there are tons of things that one should do in order to become/called a good dba but I would say that if you got a tag/job title or Database Admin, you need to make sure to do one thing, take your db’s backups constantly and test them out. If you won’t your company( or you even if you own it) will end up like this and there wont be any forgiveness from anyone. Have a read of this link from Keiths’s post,
http://www.techcrunch.com/2006/06/29/couchsurfing-deletes-itself-shuts-down/
Sad but nothing else would have been expected too.
AristDBA Is Here Everyone, Talking About Oracle Finally….
Posted by Aman Sharma in genernal on February 3, 2009
Well, here comes one more blog of mine and this time, I hope its going to stay here. I have been shuffling things a lot and so far, I have not been able to fix upon the place where I shall write about the encouters of mine with Oracle database. There is surely another blog of mine over the group that me and my friends are trying to make and push, I shall be there as well. But this blog, will be having snippets of my experiences/learnings with oracle database and its world. Hope I shall be able to write some thing useful and it will be helpful for others as well! If you are reading this, I shall appreciate any comment/suggestion about the topics about which you want me to write about, you know ”food for thought”
. Let’s see how it goes!

Recent Comments