Over the holiday period I got a credit card bill from Oracle Norway for £3230.12. I have no idea what this is for, and as far as I know I’ve never dealt with Oracle Norway before, so my bank are treating it as a credit card fraud case.
What’s more I have no idea how they got my card details because this isn’t a card I use for anything Oracle related, like travel etc.
I contacted Oracle Norway, who put me on to Oracle Romania, who have passed me on to a finance department, who have now passed me on to another finance department. As yet no indication of what I supposedly bought or did to warrant this charge. The initial issue was worrying, but what’s more worrying is the amount of time it’s taken to get any response. I guess the holidays have had an impact though.
In the short term I’m not that bothered because my bank have already refunded the cash, as is their way when investigating potential fraud cases, but I would certainly like to know how this happened in the first place so I can prevent it from happening again…
Cheers
Tim…
Just a quick note for anyone who has missed the Oracle Security alerts email. If you downloaded either Enterprise Manager 11g or Oracle Database 11.2.0.2 before November 17th last year then you downloaded a version of OUI that sent unencrypted passwords for your oracle.com SSO account to Oracle over the intertubes. Not Good. Oracle have [...]
I don’t know if you are ever asked to compare to AWR periods. AWR period comparison is pretty easy if you have access to the two periods in the same AWR repository. AWR in the same repository can be compared with
SELECT * FROM TABLE(
dbms_workload_repository.awr_diff_report_text(
[db_id ],
[instance id],
120, -- start snapshot id
121, -- end snapshot id
[db_id of target,
[instance id] ,
122, -- start snapshot id
123 -- end snapshot id));and it can be run for single instance as
SELECT * FROM TABLE(
dbms_workload_repository.awr_diff_report_text(
(select dbid from v$database),
1,
120, -- start snapshot id
121, -- end snapshot id
(select dbid from v$database),
1,
122, -- start snapshot id
123 -- end snapshot id));This puts out a bit of a messy but useful report.
A similar, but cleaner simpler report that I partially designed can be run from OEM

but what if someone sends you two AWR reports? How can they be compared? These days I’m receiving at least a couple a week to compare, so I put together a compare script.
usage:
udiffs.sh [type] file1 file2
where type
for example
udiffs.sh sevt awr1.txt awr2.txt ... Statistics requested is load ... 1st report.txt ... 2nd report.txt ============================= load_psec ============================== Name Ratio 1/2 Value1 Value2 Delta Physical_reads: : 0.29: 266.20: 905.33: 639.13 Physical_writes: : 0.70: 585.32: 836.75: 251.43 Logons: : 0.86: 1.27: 1.48: 0.21 Logical_reads: : 1.04: 747342.68: 718259.28: -29083.4 Redo_size: : 1.17:3516126.09:2995591.47: -520535 Sorts: : 1.31: 3981.16: 3027.78: -953.38 User_calls: : 1.38: 16476.53: 11948.71: -4527.82 Parses: : 1.39: 4541.51: 3279.06: -1262.45 Executes: : 1.44: 10619.75: 7350.55: -3269.2 Hard_parses: : 1.89: 0.17: 0.09: -0.08 Block_changes: : 2.38: 18936.62: 7942.27: -10994.3 ============================= load_ptrx ============================== Name Ratio 1/2 Value1 Value2 Delta Logons: : 0.00: 0.00: 0.01: 0.01 Physical_reads: : 0.11: 0.43: 3.94: 3.51 Physical_writes: : 0.26: 0.95: 3.64: 2.69 Logical_reads: : 0.39: 1218.11: 3123.70: 1905.59 Redo_size: : 0.44: 5730.99: 13027.80: 7296.81 Sorts: : 0.49: 6.49: 13.17: 6.68 User_calls: : 0.52: 26.86: 51.96: 25.1 Parses: : 0.52: 7.40: 14.26: 6.86 Executes: : 0.54: 17.31: 31.97: 14.66 Block_changes: : 0.89: 30.87: 34.54: 3.67
of course if your AWR report is an html file, then the current script won’t work. One workaround is to run the html through a text converter like
http://www.nirsoft.net/utils/htmlastext.html
Again the script is available here: udiffs.sh
I started to write this blog post more than two weeks ago when I returned home for Christmas after travelling and working away for most of the last 3 months or so teaching training classes, doing security audits and also....[Read More]
Posted by Pete On 04/01/11 At 07:21 PM
January 4, 2011 (Forward to the Next Post in the Series) While performing a Google search I encountered a couple of Oracle multiple choice quizzes that also supplied justifications for the answer that is described on the page as being correct. The web pages I found reminded me a bit of some of the quizzes that I [...]![]()
This entry goes out to my Oracle techie friends that have been in the Linux camp for sometime now and are suddenly finding themselves needing to know more about Solaris… hmmmm… I wonder if this has anything to do with Solaris now being an available option with Exadata? Or maybe the recent announcement that the SPARC T3 multiplier for T3-x servers is now 0.25. Judging by my inbox recently, I suspect a renewed interest in Solaris to continue.
First of all, may I wish everyone who comes by my blog a heartfelt Happy New Year.
Secondly, I promise I’ll blog more often and more on technical aspects this year than I have for most of 2010.
Thirdly, I’ll admit the title to this blog is nothing to do with the hardware company now owned by Mr Larry Ellison, but is about the huge glowing ball of fire in the sky (which we have not seen a lot of here in England and Wales for the last couple of weeks – not sure about Scotland but I suspect it has been the same). I apologise for the blatantly misleading (and syntactically poor) title.
A quick question for you – It is the depths of winter for most of us, and it has been unusually cold here in the UK and much of Europe. When are we, as a planet, furthest from the Sun during winter? January the 1st? The Shortest day (21st December)? The day the evening start drawing out (December 14th)?
I think many in the Northern Hemisphere will be surprised to learn that we are closest to the sun today (3rd Jan 2011). A mere 147.104 million kilometers from the centre of our solar system. I mentioned this to a few friends and they were all taken aback, thinking we would be furthest from the warmth of the sun at the depths of our winter.
Come the 4th July 2011 it is not only some strange celebration in the US about having made the terrible decision to go it alone in the world {Joke guys!}, but is the day in the year that the Earth is furthest from the sun – 152.097 million kilometers. That is about 3.39% further away and, as the energy we receive from the sun is equal to the square of the distance, does account for a bit of a drop in the energy received. {Surface of a sphere is 4*pi*(R{adius}squared), you can think of the energy from the sun as being spread over the sphere at any given distance}.
Some of you may be wondering why this furthest/closest to the sun does not match the longest/shortest day. As some of you may remember, I explained about the oddities of the shortest day not matching when the nights start drawing out about this time last year. It is because as we spin around our own pole and around the sun, things are complicated by the fact that the earth “leans over” in it’s orbit.
Check out this nice web site where you can state the location and month you want to see sunrise, sunset, day length and (of particular relevance here) the distance from the sun for each day.
I find it interesting that many of the things us most of us see as “common sense” are often not actually right (I always assumed that the shortest day coincided with both the evenings starting to draw out and mornings getting earlier until I stumbled across it when looking at sunset times – I had to go find a nice Astronomer friend to explain it all to me). I also like the fact that a very simple system – a regularly spinning ball circling a large big “fixed point” in a fixed way – throws up some oddities due to little extra considerations that often go overlooked. Isn’t that so like IT?
That lean in the Earth’s angle of spin compared to the plane we revolve around the sun is slowly rotating too, so in a few years (long, long, long after any of us will be around to care) then the furthest point in the orbit will indeed match the northern hemisphere winter. Again like IT, even the oddities keep shifting.
A couple of days ago I published a link to some comments I had made on OTN about differences in redo generation between 10g and earlier versions of Oracle. This raised a few questions that suggested a follow-up (or perhaps “prequel”) note might be a little helpful. So I’ve created a simple SQL script to help demonstrate the differences and show how some of the pieces hang together. The whole posting is a little lengthy, but a large fraction of it is just the continuous output from a couple of trace files from which I’ll be highlighting just a few lines.
drop table t1; create table t1 ( n1 number, n2 number, n3 number, n4 number ); create index i1 on t1(n1); create index i2 on t1(n2); insert into t1 values (1,1,1,1); commit; alter system switch logfile; insert into t1 values (2,2,2,2); insert into t1 values (3,3,3,3); commit; execute dump_log
All I’ve done is create a simple table with two indexes. I insert a row and commit because the first insert of a row into a table results in all sorts of funny bits of recursive activity (mostly related space management) and I want to get that out of the way so that it doesn’t obscure the more typical activity. Then I “switch logfile”, do a little work, and use a little procedure I’ve written to dump the current log file. The log file switch is just a convenient way to keep the dump small – but there are strategies for being selective about the parts of the redo log file you dump.
The work I’ve done is just two inserts into the table – this means I expect to find something like the following bits of activity listed in the redo log file:
What I’m going to show you next is the redo log file dump from Oracle 9.2.0.8 and then the corresponding redo log file dump from 10.2.0.3.
In the 9.2.0.8 dump we’ll see the “traditional” sequence of redo generation, which follows very closely to the steps listed above and also shows that Oracle pairs a “redo change vector” for a table or index block with the matching “redo change vector” for an undo record that describes how to reverse the table (or index) change – an undo record, of course, is just a piece of information that gets stored in an undo block. In general, each pair of redo change vectors will be gathered into a single “redo record”.
In the 10.2.0.3 dump we’ll see that the same redo change vectors still exist but they’ve all been lumped into a single redo record, and their ordering in that record is completely different from the 9.2.0.8 ordering, demonstrating (or at least supporting) the point that the “private redo/in-memory undo” mechanism uses two separate buffers, one for redo change vectors related to table/index blocks (the private redo bit) and the other for redo change vectors related to undo records (the in-memory undo bit).
The key expressions to watch out for in the dump are: “REDO RECORD” and “CHANGE #” (I’ve inserted a few blank lines into the trace file to give a little white space between records and vectors):
REDO RECORD - Thread:1 RBA: 0x000360.00000002.0010 LEN: 0x0170 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:23 AFN:2 DBA:0x00800039 SCN:0x0000.03ec99bf SEQ: 1 OP:5.2 ktudh redo: slt: 0x0016 sqn: 0x00001a69 flg: 0x0012 siz: 80 fbi: 0 uba: 0x00800040.075d.26 pxid: 0x0000.000.00000000 CHANGE #2 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99be SEQ: 1 OP:5.1 ktudb redo: siz: 80 spc: 2708 flg: 0x0012 seq: 0x075d rec: 0x26 xid: 0x0004.016.00001a69 ktubl redo: slt: 22 rci: 0 opc: 11.1 objn: 45648 objd: 45648 tsn: 12 Undo type: Regular undo Begin trans Last buffer split: No Temp Object: No Tablespace Undo: No 0x00000000 prev ctl uba: 0x00800040.075d.25 prev ctl max cmt scn: 0x0000.03ebf084 prev tx cmt scn: 0x0000.03ebf106 KDO undo record: KTB Redo op: 0x03 ver: 0x01 op: Z KDO Op code: DRP row dependencies Disabled xtype: XA bdba: 0x02c0000a hdba: 0x02c00009 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) CHANGE #3 TYP:2 CLS: 1 AFN:11 DBA:0x02c0000a SCN:0x0000.03ec99f2 SEQ: 1 OP:11.2 KTB Redo op: 0x01 ver: 0x01 op: F xid: 0x0004.016.00001a69 uba: 0x00800040.075d.26 KDO Op code: IRP row dependencies Disabled xtype: XA bdba: 0x02c0000a hdba: 0x02c00009 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) size/delt: 15 fb: --H-FL-- lb: 0x2 cc: 4 null: ---- col 0: [ 2] c1 03 col 1: [ 2] c1 03 col 2: [ 2] c1 03 col 3: [ 2] c1 03 CHANGE #4 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:5.20 session number = 9 serial number = 6 transaction name = -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000002.0180 LEN: 0x0108 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99f5 SEQ: 1 OP:5.1 ktudb redo: siz: 96 spc: 2626 flg: 0x0022 seq: 0x075d rec: 0x27 xid: 0x0004.016.00001a69 ktubu redo: slt: 22 rci: 38 opc: 10.22 objn: 45649 objd: 45649 tsn: 12 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x04 ver: 0x01 op: L itl: xid: 0x000a.012.00002552 uba: 0x0080009c.09cb.0c flg: C--- lkc: 0 scn: 0x0000.03ec99f2 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=96880916 indexid=0x2c00409 block=0x02c0040a purge leaf row key: (10): 02 c1 03 06 02 c0 00 0a 00 01 CHANGE #2 TYP:2 CLS: 1 AFN:11 DBA:0x02c0040a SCN:0x0000.03ec99f2 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x11 ver: 0x01 op: F xid: 0x0004.016.00001a69 uba: 0x00800040.075d.27 Block cleanout record, scn: 0x0000.03ec99f5 ver: 0x01 opt: 0x02, entries follow... itli: 2 flg: 2 scn: 0x0000.03ec99f2 REDO: SINGLE / -- / -- itl: 2, sno: 1, row size 14 insert key: (10): 02 c1 03 06 02 c0 00 0a 00 01 -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000003.0098 LEN: 0x0108 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99f5 SEQ: 2 OP:5.1 ktudb redo: siz: 96 spc: 2528 flg: 0x0022 seq: 0x075d rec: 0x28 xid: 0x0004.016.00001a69 ktubu redo: slt: 22 rci: 39 opc: 10.22 objn: 45650 objd: 45650 tsn: 12 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x04 ver: 0x01 op: L itl: xid: 0x000a.012.00002552 uba: 0x0080009c.09cb.0d flg: C--- lkc: 0 scn: 0x0000.03ec99f2 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=96880916 indexid=0x2c00489 block=0x02c0048a purge leaf row key: (10): 02 c1 03 06 02 c0 00 0a 00 01 CHANGE #2 TYP:2 CLS: 1 AFN:11 DBA:0x02c0048a SCN:0x0000.03ec99f2 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x11 ver: 0x01 op: F xid: 0x0004.016.00001a69 uba: 0x00800040.075d.28 Block cleanout record, scn: 0x0000.03ec99f5 ver: 0x01 opt: 0x02, entries follow... itli: 2 flg: 2 scn: 0x0000.03ec99f2 REDO: SINGLE / -- / -- itl: 2, sno: 1, row size 14 insert key: (10): 02 c1 03 06 02 c0 00 0a 00 01 -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000003.01a0 LEN: 0x00f4 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99f5 SEQ: 3 OP:5.1 ktudb redo: siz: 64 spc: 2430 flg: 0x0022 seq: 0x075d rec: 0x29 xid: 0x0004.016.00001a69 ktubu redo: slt: 22 rci: 40 opc: 11.1 objn: 45648 objd: 45648 tsn: 12 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 KDO undo record: KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.26 KDO Op code: DRP row dependencies Disabled xtype: XA bdba: 0x02c0000a hdba: 0x02c00009 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 2(0x2) CHANGE #2 TYP:0 CLS: 1 AFN:11 DBA:0x02c0000a SCN:0x0000.03ec99f5 SEQ: 1 OP:11.2 KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.29 KDO Op code: IRP row dependencies Disabled xtype: XA bdba: 0x02c0000a hdba: 0x02c00009 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 2(0x2) size/delt: 15 fb: --H-FL-- lb: 0x2 cc: 4 null: ---- col 0: [ 2] c1 04 col 1: [ 2] c1 04 col 2: [ 2] c1 04 col 3: [ 2] c1 04 -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000004.00a4 LEN: 0x00c8 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99f5 SEQ: 4 OP:5.1 ktudb redo: siz: 80 spc: 2364 flg: 0x0022 seq: 0x075d rec: 0x2a xid: 0x0004.016.00001a69 ktubu redo: slt: 22 rci: 41 opc: 10.22 objn: 45649 objd: 45649 tsn: 12 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.27 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=96880916 indexid=0x2c00409 block=0x02c0040a purge leaf row key: (10): 02 c1 04 06 02 c0 00 0a 00 02 CHANGE #2 TYP:0 CLS: 1 AFN:11 DBA:0x02c0040a SCN:0x0000.03ec99f5 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.2a REDO: SINGLE / -- / -- itl: 2, sno: 2, row size 14 insert key: (10): 02 c1 04 06 02 c0 00 0a 00 02 -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000004.016c LEN: 0x00c8 VLD: 0x01 SCN: 0x0000.03ec99f5 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:24 AFN:2 DBA:0x00800040 SCN:0x0000.03ec99f5 SEQ: 5 OP:5.1 ktudb redo: siz: 80 spc: 2282 flg: 0x0022 seq: 0x075d rec: 0x2b xid: 0x0004.016.00001a69 ktubu redo: slt: 22 rci: 42 opc: 10.22 objn: 45650 objd: 45650 tsn: 12 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.28 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=96880916 indexid=0x2c00489 block=0x02c0048a purge leaf row key: (10): 02 c1 04 06 02 c0 00 0a 00 02 CHANGE #2 TYP:0 CLS: 1 AFN:11 DBA:0x02c0048a SCN:0x0000.03ec99f5 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800040.075d.2b REDO: SINGLE / -- / -- itl: 2, sno: 2, row size 14 insert key: (10): 02 c1 04 06 02 c0 00 0a 00 02 -------------- REDO RECORD - Thread:1 RBA: 0x000360.00000005.0044 LEN: 0x0070 VLD: 0x01 SCN: 0x0000.03ec99f6 SUBSCN: 1 12/30/2010 14:36:06 CHANGE #1 TYP:0 CLS:23 AFN:2 DBA:0x00800039 SCN:0x0000.03ec99f5 SEQ: 1 OP:5.4 ktucm redo: slt: 0x0016 sqn: 0x00001a69 srt: 0 sta: 9 flg: 0x12 ktucf redo: uba: 0x00800040.075d.2b ext: 0 spc: 2200 fbi: 0
The dump from 9.2.0.8 consists of seven redo records – and most of those records consist of two redo change vectors. We’ll start by looking at the fourth redo record (starting at line 112) which is a typical “old-style” redo record. It consists of two redo change vectors.
In the chosen record, change #1 (line 115) describes how to change an undo block at address (DBA) 0×00800040 which is operating at sequence number (seq: ) 0x075d. The change is to insert a new undo record, with record number (rec: ) 0×29. If you look at lines 126 – 129 you see that this undo record is an instruction to Delete a Row Piece (DRP) from data block (bdba) 0x02c0000a; the row piece is identified as the pointed to by slot 2 of table 0 in the block’s row directory.
Change # 2 (line 131) describes the change needed to create that row piece (note the IRP – Insert Row Piece at line 135). Again we see references to the block, table number and slot number.
The next two redo records are very similar: they describe how to insert and delete a key entry for each of the two indexes that have to be maintained as the row is inserted into the table – again the redo change vector for the “undo” appears before the redo change vector for the “apply”.
The first three redo records form a similar group – the first one is about inserting/removing a table row, the second and third are about the insert/remove pairs for the two indexes – but the first record of the three is more complex, consisting of four redo change vectors rather than just two.
The first redo record happens to be the first record of the transaction – so it contains (for 9i and below) two extra redo change vectors. The standard pair for the table row appear as change #2 and change #3, but in change #1 we see the redo change vector describing a change to the undo segment header block (line 5: ktudh) as we acquire a “transaction table slot” (see my glossary, and “cleanout”) specifically slot 0×0016, which we stamp with sequence number 0x00001a69. The final change vector in this record (change #4 at line 41) is marked as a “Media Recovery Marker” – it’s actually a type of audit label – and the example here is the short form; there is a much longer version used for the first transaction of a session’s lifetime, which is also used after each log file switch that takes place in a session’s lifetime (and in 8i there was a bug that meant the full vector appeared for every transaction start – with could result in a nasty volume of excess redo).
The last redo record is the so-called “commit record”. It consists of just one change vector (line 209). This change vector describes the update to the undo segment header as we commit (ktucm) the transaction; the status (sta: ) of transaction table slot 0×0016 is set to 9 to show that the slot is now free, and the “free pool” list (ktucf) is updated to show that the last undo block we were using has some space available in it that could be used by the next transaction that acquires a slot in this undo segment.
So that’s the redo generated by 9i. The basic pattern is that a typical redo record consists of a pair of redo change vectors, the first describing an undo record and the second describing how to make the required data change.
An important scalability detail (or threat, rather) that goes with this implementation is that the session has to allocate memory in the redo log buffer and copy each redo record in turn so, for our table with two indexes, every row we insert requires us to acquire the redo allocation latch and redo copy latch three times.
Now we move on to see what shows up in the log file when we run our code on 10.2.0.3
REDO RECORD - Thread:1 RBA: 0x00034b.00000002.0010 LEN: 0x0638 VLD: 0x0d SCN: 0x0000.00d60a85 SUBSCN: 1 12/30/2010 14:24:01 CHANGE #1 TYP:2 CLS: 1 AFN:6 DBA:0x01804d8a OBJ:70577 SCN:0x0000.00d60a81 SEQ: 5 OP:11.2 KTB Redo op: 0x01 ver: 0x01 op: F xid: 0x0008.025.00003632 uba: 0x008031d3.07f1.27 KDO Op code: IRP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x01804d8a hdba: 0x01804d89 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) size/delt: 15 fb: --H-FL-- lb: 0x2 cc: 4 null: ---- col 0: [ 2] c1 03 col 1: [ 2] c1 03 col 2: [ 2] c1 03 col 3: [ 2] c1 03 CHANGE #2 TYP:0 CLS:31 AFN:2 DBA:0x00800079 OBJ:4294967295 SCN:0x0000.00d60a5f SEQ: 1 OP:5.2 ktudh redo: slt: 0x0025 sqn: 0x00003632 flg: 0x0012 siz: 104 fbi: 0 uba: 0x008031d3.07f1.27 pxid: 0x0000.000.00000000 CHANGE #3 TYP:2 CLS: 1 AFN:6 DBA:0x01804e0a OBJ:70578 SCN:0x0000.00d60a81 SEQ: 2 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x11 ver: 0x01 op: F xid: 0x0008.025.00003632 uba: 0x008031d3.07f1.28 Block cleanout record, scn: 0x0000.00d60a84 ver: 0x01 opt: 0x02, entries follow... itli: 2 flg: 2 scn: 0x0000.00d60a81 REDO: SINGLE / -- / -- itl: 2, sno: 1, row size 14 insert key: (10): 02 c1 03 06 01 80 4d 8a 00 01 CHANGE #4 TYP:2 CLS: 1 AFN:6 DBA:0x01804e8a OBJ:70579 SCN:0x0000.00d60a81 SEQ: 2 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x11 ver: 0x01 op: F xid: 0x0008.025.00003632 uba: 0x008031d3.07f1.29 Block cleanout record, scn: 0x0000.00d60a84 ver: 0x01 opt: 0x02, entries follow... itli: 2 flg: 2 scn: 0x0000.00d60a81 REDO: SINGLE / -- / -- itl: 2, sno: 1, row size 14 insert key: (10): 02 c1 03 06 01 80 4d 8a 00 01 CHANGE #5 TYP:0 CLS: 1 AFN:6 DBA:0x01804d8a OBJ:70577 SCN:0x0000.00d60a85 SEQ: 1 OP:11.2 KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.2a KDO Op code: IRP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x01804d8a hdba: 0x01804d89 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 2(0x2) size/delt: 15 fb: --H-FL-- lb: 0x2 cc: 4 null: ---- col 0: [ 2] c1 04 col 1: [ 2] c1 04 col 2: [ 2] c1 04 col 3: [ 2] c1 04 CHANGE #6 TYP:0 CLS: 1 AFN:6 DBA:0x01804e0a OBJ:70578 SCN:0x0000.00d60a85 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.2b REDO: SINGLE / -- / -- itl: 2, sno: 2, row size 14 insert key: (10): 02 c1 04 06 01 80 4d 8a 00 02 CHANGE #7 TYP:0 CLS: 1 AFN:6 DBA:0x01804e8a OBJ:70579 SCN:0x0000.00d60a85 SEQ: 1 OP:10.2 index redo (kdxlin): insert leaf row KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.2c REDO: SINGLE / -- / -- itl: 2, sno: 2, row size 14 insert key: (10): 02 c1 04 06 01 80 4d 8a 00 02 CHANGE #8 TYP:0 CLS:31 AFN:2 DBA:0x00800079 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 1 OP:5.4 ktucm redo: slt: 0x0025 sqn: 0x00003632 srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x008031d3.07f1.2c ext: 38 spc: 1718 fbi: 0 CHANGE #9 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a5d SEQ: 1 OP:5.1 ktudb redo: siz: 104 spc: 2250 flg: 0x0012 seq: 0x07f1 rec: 0x27 xid: 0x0008.025.00003632 ktubl redo: slt: 37 rci: 0 opc: 11.1 objn: 70577 objd: 70577 tsn: 5 Undo type: Regular undo Begin trans Last buffer split: No Temp Object: No Tablespace Undo: No 0x00000000 prev ctl uba: 0x008031d3.07f1.26 prev ctl max cmt scn: 0x0000.00d5fa91 prev tx cmt scn: 0x0000.00d5fb64 txn start scn: 0x0000.00d60a81 logon user: 52 prev brb: 8401354 prev bcl: 0 KDO undo record: KTB Redo op: 0x03 ver: 0x01 op: Z KDO Op code: DRP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x01804d8a hdba: 0x01804d89 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) CHANGE #10 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 1 OP:5.1 ktudb redo: siz: 96 spc: 2144 flg: 0x0022 seq: 0x07f1 rec: 0x28 xid: 0x0008.025.00003632 ktubu redo: slt: 37 rci: 39 opc: 10.22 objn: 70578 objd: 70578 tsn: 5 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x04 ver: 0x01 op: L itl: xid: 0x0005.01e.000035e3 uba: 0x008034a5.083a.1d flg: C--- lkc: 0 scn: 0x0000.00d60a81 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x1804e09 block=0x01804e0a (kdxlpu): purge leaf row key: (10): 02 c1 03 06 01 80 4d 8a 00 01 CHANGE #11 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 2 OP:5.1 ktudb redo: siz: 96 spc: 2046 flg: 0x0022 seq: 0x07f1 rec: 0x29 xid: 0x0008.025.00003632 ktubu redo: slt: 37 rci: 40 opc: 10.22 objn: 70579 objd: 70579 tsn: 5 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x04 ver: 0x01 op: L itl: xid: 0x0005.01e.000035e3 uba: 0x008034a5.083a.1e flg: C--- lkc: 0 scn: 0x0000.00d60a81 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x1804e89 block=0x01804e8a (kdxlpu): purge leaf row key: (10): 02 c1 03 06 01 80 4d 8a 00 01 CHANGE #12 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 3 OP:5.1 ktudb redo: siz: 64 spc: 1948 flg: 0x0022 seq: 0x07f1 rec: 0x2a xid: 0x0008.025.00003632 ktubu redo: slt: 37 rci: 41 opc: 11.1 objn: 70577 objd: 70577 tsn: 5 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 KDO undo record: KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.27 KDO Op code: DRP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x01804d8a hdba: 0x01804d89 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 2(0x2) CHANGE #13 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 4 OP:5.1 ktudb redo: siz: 80 spc: 1882 flg: 0x0022 seq: 0x07f1 rec: 0x2b xid: 0x0008.025.00003632 ktubu redo: slt: 37 rci: 42 opc: 10.22 objn: 70578 objd: 70578 tsn: 5 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.28 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x1804e09 block=0x01804e0a (kdxlpu): purge leaf row key: (10): 02 c1 04 06 01 80 4d 8a 00 02 CHANGE #14 TYP:0 CLS:32 AFN:2 DBA:0x008031d3 OBJ:4294967295 SCN:0x0000.00d60a85 SEQ: 5 OP:5.1 ktudb redo: siz: 80 spc: 1800 flg: 0x0022 seq: 0x07f1 rec: 0x2c xid: 0x0008.025.00003632 ktubu redo: slt: 37 rci: 43 opc: 10.22 objn: 70579 objd: 70579 tsn: 5 Undo type: Regular undo Undo type: Last buffer split: No Tablespace Undo: No 0x00000000 index undo for leaf key operations KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x008031d3.07f1.29 Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x1804e89 block=0x01804e8a (kdxlpu): purge leaf row key: (10): 02 c1 04 06 01 80 4d 8a 00 02
The entire transaction is wrapped up into a single redo record with fourteen redo change vectors. (The 9i dump showed a total of fifteen redo change vectors – we’ve lost the “audit” vector in our 10g setup.) In order, the vectors describe how to…
It is reasonable to infer from this that Oracle is generating a list of “forward” changes (i.e. the private redo) in one buffer and a list of “reverse” changes (i.e. the in-memory undo) in another buffer – and simply concatenates the two lists on the commit.
On the plus side, if we’ve only got one redo record we only have to allocate and copy into the (public) redo buffer once – which reduces contention on a single important hot spot in the Oracle database; on the other hand we have to keep a number of data blocks pinned in memory until the commit, and we have to modify all those data blocks at the same time as we copy the two private buffers into the (public) redo log buffer, and this requirement introduces a different concurrency threat.
Because of this alternative threat there is a fairly tight limit on how much change a single transaction is allowed to make using this new mechanism . For 32-bit Oracle the buffers are about 64Kb each, and for 64-bit Oracle they are about 128KB – and if a session fills either of the two buffers it has acquired then Oracle flushes the contents to the public log buffer and the session then carries on using the public log buffer in the “traditional” way (while still keeping “ownership” of the pair of private buffers that it had allocated.)
A final thought – if you issue a rollback instead of a commit, the “commit record” (change #8 in the above) disappears from the redo record, and the redo stream gets a further six redo records showing how each of the previous undo records have been applied at the user’s request; these records are followed by one last redo record which describes the release of the transaction table slot i.e. a “commit record”.
Myth: Oracle has a Central Locking System
A week or so ago I started a new series – 100 Things You Probably didn’t Know about Oracle Database . Part 1 of the series proved quite popular, as I surmise from the emails I received. Here is the Part 2 of the series.
When a transaction updates a row, it puts a lock so that no one can update the same row until it commits. When another transaction issues an update to the same row, it waits until the first one either commits or rolls back. After the first transaction performs a commit or rollback, the update by the second transaction is executed immediately, since the lock placed by the first transaction is now gone. How exactly does this locking mechanism work? Several questions come to mind in this context:
If you are interested to learn about all this, please read on.
Lock Manager
Since locks convey information on who has what rows modified but not committed, anyone interested in making the update much check with some sort of system that is available across the entire database. So, it makes perfect sense to have a central locking system in the database, doesn’t it? But, when you think about it, a central lock manager can quickly become a single point of contention in a busy system where a lot of updates occur. Also, when a large number of rows are updated in a single transaction, an equally large number of locks will be required as well. The question is: how many? One can guess; but it will be at best a wild one. What if you guessed on the low side and the supply of available locks is depleted? In that case some transactions can’t get locks and therefore will have to wait (or, worse, abort). Not a pleasant thought in a system that needs to be scalable. To counter such a travesty you may want to make the available supply of locks really high. What is the downside of that action? Since each lock would potentially consume some memory, and memory is finite, it would not be advisable to create an infinite supply of locks.
Some databases actually have a lock manager with a finite supply of such locks. Each transaction must ask to get a lock from it before beginning and relinquish locks to it at the completion. In those technologies, the scalability of application suffers immensely as a result of the lock manager being the point of contention. In addition, since the supply of locks is limited, the developers need to commit frequently to release the locks for other transactions. When a large number of rows have locks on them, the database replaces the row locks with a block level lock to cover all the rows in the block – a concept known as lock escalation. Oracle does not follow that approach. In Oracle, there no central lock manager, no finite limit on locks and there is no such concept called lock escalation. The developers commit only when there is a logical need to do so; not otherwise.
Lock Management in Oracle
So, how is that approach different in case of Oracle? For starters, there is no central lock manager. But the information on locking has to be recorded somewhere. Where then? Well, consider this: when a row is locked, it must be available to the session, which means the session’s server process must have already accessed and placed the block in the buffer cache prior to the transaction occurring. Therefore, what is a better place for putting this information than right there in the block (actually the buffer in the buffer cache) itself?
Oracle does precisely that – it records the information in the block. When a row is locked by a transaction, that nugget of information is placed in the header of the block where the row is located. When another transaction wishes to acquire the lock on the same row, it has to access the block containing the row anyway (as you learned in Part 1 of this series) and upon reaching the block, it can easily confirm that the row is locked from the block header. A transaction looking to update a row in a different block puts that information on the header of that block. There is no need to queue behind some single central resource like a lock manager. Since lock information is spread over multiple blocks instead of a single place, this mechanism makes transactions immensely scalable.
Being the smart reader you are, you are now hopefully excited to learn more or perhaps you are skeptical. You want to know the nuts and bolts of this whole mechanism and, more, you want proof. We will see all that in a moment.
Transaction Address
Before understanding the locks, you should understand clearly what a transaction is and how it is addressed. A transaction starts when an update to data such as insert, update or delete occurs (or the intention to do so, e.g. SELECT FOR UPDATE) and ends when the session issues a commit or rollback. Like everything else, a specific transaction should have a name or an identifier to differentiate it from another one of the same type. Each transaction is given a transaction ID. When a transaction updates a row (it could also insert a new row or delete an existing one; but we will cover that little later in this article), it records two things:
The old value is recorded in the undo segments while the new value is immediately updated in the buffer where the row is stored. The data buffer containing the row is updated regardless of whether the transaction is committed or not. Yes, let me repeat – the data buffer is updated as soon as the transaction modifies the row (before commit). If you didn’t know that, please see the Part 1 of this series.
Undo information is recorded in a circular fashion. When new undo is created, it is stored in the next available undo “slot”. Each transaction occupies a record in the slot. After all the slots are exhausted and a new transaction arrives, the next processing depends on the state of the transactions. If the oldest transaction occupying any of the other slots is no longer active (that is either committed or rolled back), Oracle will reuse that slot. If none of the transactions is inactive, Oracle will have to expand the undo tablespace to make room. In the former case (where a transaction is no longer active and its information in undo has been erased by a new transaction), if a long running query that started before the transaction occurred selects the value, it will get an ORA-1555 error. But that will be covered in a different article in the future. If the tablespace containing the undo segment can’t extend due to some reason (such as in case of the filesystem being completely full), the transaction will fail.
Speaking of transaction identifiers, it is in the form of three numbers separated by periods. These three numbers are:
This is sort of like the social security number of the transaction. This information is recorded in the block header. Let’s see the proof now through a demo.
Demo
First, create a table:
SQL> create table itltest (col1 number, col2 char(8));
Insert some rows into the table.
SQL> begin
2 for i in 1..10000 loop
3 insert into itltest values (i,'x');
4 end loop;
5 commit;
6 end;
7 /
Remember, this is a single transaction. It started at the “BEGIN” line and ended at “COMMIT”. The 10,000 rows were all inserted as a part of the same transaction. To know the transaction ID of this transaction, Oracle provides a special package - dbms_transaction. Here is how you use it. Remember, you must use it in the same transaction. Let’s see:
SQL> select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
------------------------------------------------------------------------
1 row selected.
Wait? There is nothing. The transaction ID returned is null. How come?
If you followed the previous section closely, you will realize that the transaction ends when a commit or rollback is issued. The commit was issued inside the PL/SQL block. So, the transaction had ended before you called the dbms_transaction is package. Since there was no transaction, the package returned null.
Let’s see another demo. Update one row:
SQL> update itltest set col2 = 'y' where col1 = 1;
1 row updated.
In the same session, check the transaction ID:
SQL> select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
-------------------------------------------------------------------------
3.23.40484
1 row selected.
There you see – the transaction ID. The three numbers separated by period signify undo segment number, slot# and record# respectively. Now perform a commit:
SQL> commit;
Commit complete.
Check the transaction ID again:
SQL> select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
-------------------------------------------------------------------------
1 row selected.
The transaction is gone so the ID is null, as expected.
Since the call to the package must be in the same transaction (and therefore in the same session), how can you check the transaction in a different session? In real life you will be asked to check transaction in other sessions, typically application sessions. Let’s do a slightly different test. Update the row one more time and check the transaction:
SQL> update itltest set col2 = 'y' where col1 = 1;
1 row updated.
SQL> select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
-----------------------------------------------------------------------
10.25.31749
1 row selected.
From a different session, check for active transactions. This information is available in the view V$TRANSACTION. There are several columns; but we will look at four of the most important ones:
SQL> select addr, xidusn, xidslot, xidsqn
2 from v$transaction;
ADDR XIDUSN XIDSLOT XIDSQN
-------- ---------- ---------- ----------
3F063C48 10 25 31749
Voila! You see the transaction id of the active transaction from a different session. Compare the above output to the one you got from the call to dbms_transaction package. You can see that the transaction identifier shows the same set of numbers.
Interested Transaction List
You must be eager to know about the section of the block header that contains information on locking and how it records it. It is a simple data structure called "Interested Transaction List" (ITL), a list that maintains information on transaction. The ITL contains several placeholders (or slots) for transactions. When a row in the block is locked for the first time, the transaction places a lock in one of the slots. In other words, the transaction makes it known that it is interested in some rows (hence the term "Interested Transaction List"). When a different transaction locks another set of rows in the same block, that information is stored in another slot and so on. When a transaction ends after a commit or a rollback, the locks are released and the slot which was used to mark the row locks in the block is now considered free (although it is not updated immediately - fact about which you will learn later in a different installment).
#45818e;">[Updated Jan 22, 2011] [Thank you, Randolph Geist (#45818e;">info@www.sqltools-plusplus.org#45818e;">) for pointing it out. I follow his blog #45818e;">http://oracle-randolf.blogspot.com/#45818e;">, which is a treasure trove of information.
The row also stores a bit that represents the whether it is locked or not.
#45818e;">[end of Update Jan 22, 2011]
#45818e;">
ITLs in Action
Let's see how ITLs really work. Here is an empty block. The block header is the only occupant of the block.
This is how the block looks like after a single row has been inserted:
Note, the row was inserted from the bottom of the block. Now, a second row has been inserted:
A session comes in and updates the row Record1, i.e. it places a lock on the row, shown by the star symbol. The lock information is recorded in the ITL slot in the block header:
The session does not commit yet; so the lock is active. Now a second session - Session 2 - comes in and updates row Record2. It puts a lock on the record - as stored in the ITL slot.
I have used two different colors to show the locks (as shown by the star symbol) and the color of the ITL entry.
As you can clearly see, when a transaction wants to update a specific row, it doesn’t have to go anywhere but the block header itself to know if the row is locked or not. All it has to do is to check the ITL slots. However ITL alone does not show with 100% accuracy that row is locked (again, something I will explain in a different installment). The transaction must go to the undo segment to check if the transaction has been committed. How does it know which specifci part of the undo segment to go to? Well, it has the information in the ITL entry. If the row is indeed locked, the transaction must wait and retry. As soon as the previous transaction ends, the undo information is updated and the waiting transaction completes its operation.
So, there is in fact a queue for the locks, but it's at the block level, not at the level of the entire database or even the segment.
Demo
The proof is in the pudding. Let’s see all this through a demo. Now that you know the transaction entry, let’s see how it is stored in the block header. To do that, first, we need to know which blocks to look for. So, we should get the blocks numbers where the table is stored:
SQL> select file_id, relative_fno, extent_id, block_id, blocks
2 from dba_extents
3 where segment_name = 'ITLTEST';
FILE_ID RELATIVE_FNO EXTENT_ID BLOCK_ID BLOCKS
---------- ------------ ---------- ---------- ----------
7 7 0 3576 8
7 7 1 3968 8
7 7 2 3976 8
7 7 3 3984 8
To check inside the block, we need to “dump” the contents of the block to a tracefile so that we can read it. From a different session issue a checkpoint so that the buffer data is now written to the dis:
SQL> alter system checkpoint;
Now dump the data blocks 3576 through 3583.
SQL> alter system dump datafile 7 block min 3576 block max 3583;
System altered.
This will create a tracefile in the user dump destination directory. In case of Oracle 11g, the tracefile will be in the diag structure under
SQL> select p.spid
2 from v$session s, v$process p
3 where s.sid = (select sid from v$mystat where rownum < 2)
4 and p.addr = s.paddr
5 /
SPID
------------------------
9202
1 row selected.
Now look for a file named
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000a.019.00007c05 0x00c00288.1607.0e ---- 1 fsc 0x0000.00000000
0x02 0x0003.017.00009e24 0x00c00862.190a.0f C--- 0 scn 0x0000.02234e2b
This is where the information on row locking is stored. Remember, the row locking information is known as Interested Transaction List (ITL) and each ITL is stored in a “slot”. Here it shows two slots, which is the default number. Look for the one where the “Lck” column shows a value. It shows “1”, meaning one of the rows in the blocks is locked by a transaction. But, which transaction? To get that answer, note the value under the “Xid” column. It shows the transaction ID - 0x000a.019.00007c05. These numbers are in hexadecimal (as indicated by the 0x at the beginning of the number). Using the scientific calculator in Windows, I converted the values to decimal as 10, 25 and 31749 respectively. Do they sound familiar? Of course they do; they are exactly as reported by both the record in v$transaction and the dbms_transaction.local_transaction_id function call.
SQL> select addr, xidusn, xidslot, xidsqn, ubafil, ubablk, ubasqn, ubarec,
2 status, start_time, start_scnb, start_scnw, ses_addr
3 from v$transaction;
ADDR XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBASQN
-------- ---------- ---------- ---------- ---------- ---------- ----------
UBAREC STATUS START_TIME START_SCNB START_SCNW SES_ADDR
---------- ---------------- -------------------- ---------- ---------- --------
3F063C48 10 25 31749 3 648 5639
14 ACTIVE 12/30/10 20:00:25 35868240 0 40A73784
1 row selected.
The columns with names starting with UBA show the undo block address information. Look at the above output. The UBAFIL shows the file#, which is “3” in this case. Checking for the file_id:
SQL> select * from dba_data_files
2> where file_id = 3;
FILE_NAME
-------------------------------------------------------------------------
FILE_ID TABLESPACE_NAME BYTES BLOCKS STATUS
---------- ------------------------------ ---------- ---------- ---------
RELATIVE_FNO AUT MAXBYTES MAXBLOCKS INCREMENT_BY USER_BYTES USER_BLOCKS
------------ --- ---------- ---------- ------------ ---------- -----------
ONLINE_
-------
+DATA/d112d2/datafile/undotbs1.260.722742813
3 UNDOTBS1 4037017600 492800 AVAILABLE
3 YES 3.4360E+10 4194302 640 4035969024 492672
ONLINE
1 row selected.
Note the UBASQN (which is the undo block sequence#) value in the earlier output, which was 5639. Let’s revisit the ITL entries in the dump of block:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000a.019.00007c05 0x00c00288.1607.0e ---- 1 fsc 0x0000.00000000
0x02 0x0003.017.00009e24 0x00c00862.190a.0f C--- 0 scn 0x0000.02234e2b
Look at the entry under the Uba column: 0x00c00288.1607.0e. As indicated by the “0x” at the beginning, these are in hexadecimal. Using a scientific calculator, let’s convert them. 1607 in hex means 5639 in decimal – the UBA Sequence# (UBASQN). The value “e” is 14 in decimal, which corresponds to the UBAREC. Finally the value 288 is 648 in decimal, which is the UBABLK. Now you see how the information is recorded in the block header and is also available to the DBA through the view V$TRANSACTION.
SQL> select sid, username
2 from v$session
3 where saddr = '40A73784';
SID USERNAME
--- --------
123 ARUP
There you go – you now have the SID of the session. And now that you know the SID, you can look up any other relevant data on the session from the view V$SESSION.
Takeaways
Here is a summary of what you learned so far:
I hope you found it useful. As always, I will be grateful to know how you liked it. In the next installment we will examine how these ITLs could cause issues and how to identify or resolve them.
January 3, 2011 A couple of days ago I used a NO_QUERY_TRANSFORMATION hint to permit a query (provided by Martin Berger) to execute, which on the surface appeared to be quite sane, but without hints the query would usually fail to execute. A test case version of the query worked on 11.2.0.1 running on 64 bit Windows on [...]![]()
Recent comments
17 weeks 1 day ago
26 weeks 6 days ago
28 weeks 4 days ago
31 weeks 6 days ago
34 weeks 1 day ago
43 weeks 4 days ago
45 weeks 1 day ago
46 weeks 1 day ago
46 weeks 2 days ago
49 weeks 19 hours ago