June 7, 2011
While reading through the alpha copy of a performance tuning book, I noticed a set of SQL statements that were identical to those found in the Oracle Database 11.2 Performance Tuning Guide. The set of SQL statements from the Performance Tuning Guide follow:
10.3.1.1 Causes
To determine the possible causes, first query V$SESSION to identify the value of ROW_WAIT_OBJ# when the session waits for buffer busy waits. For example:SELECT row_wait_obj# FROM V$SESSION WHERE EVENT = 'buffer busy waits';To identify the object and object type contended for, query DBA_OBJECTS using the value for ROW_WAIT_OBJ# that is returned from V$SESSION. For example:
SELECT owner, object_name, subobject_name, object_type FROM DBA_OBJECTS WHERE data_object_id = &row_wait_obj;
In an earlier article we found that V$SESSION’s ROW_WAIT_OBJ# column indicated the OBJECT_ID, not the DATA_OBJECT_ID of the object (as found in DBA_OBJECTS) and the same was true for the obj# entry found in a 10046 trace file. When you first create an index the OBJECT_ID and the DATA_OBJECT_ID values will be the same for the index, as displayed in DBA_OBJECTS. However, when you rebuild the index the DATA_OBJECT_ID value for the index will change while the OBJECT_ID value remains unchanged. Likewise, when you first create a table the OBJECT_ID and the DATA_OBJECT_ID values will be the same, as displayed in DBA_OBJECTS. If you TRUNCATE a table, the OBJECT_ID value will remain the same while the DATA_OBJECT_ID value for the table will change.
The challenge is to build a test case that either confirms or refutes the claim made by the Oracle Database Performance Tuning Guide. Possible references:
- AskTom thread
- Metalink (MOS) ID 15476.1 “FAQ about Detecting and Resolving Locking Conflicts”
- Metalink (MOS) Doc ID 603661.1 “ORA-01410: Invalid Rowid When Using rowid Generated from V$Session and Dba_objects”
- Another article found on this blog (take a look at the Other Resources links)
Modifying my testcase from your earlier post https://hoopercharles.wordpress.com/2010/06/03/lock-watching-what-is-wrong-with-this-sql-statement/
This
produces this:
Flado,
Thanks for the example. However, for this specific article I was curious as to whether someone could demonstrate whether or not the presence of a “buffer busy waits” wait event indicates that the ROW_WAIT_OBJ# column shows the DATA_OBJECT_ID rather than the OBJECT_ID, as indicated in the Oracle Database Performance Tuning Guide and the alpha copy of the book. Your example, did however, cause me to scroll down a bit further in the Performance Tuning Guide (and flip to part 6-6 of the alpha copy of the book). That part of the Performance Tuning Guide:
http://download.oracle.com/docs/cd/E14072_01/server.112/e10821/instance_tune.htm#PFGRF94484
Includes the following set of SQL statements:
The alpha copy of the book performs the following join, where DBA_OBJECTS is aliased as “b” and V$SESSION is aliased as “a” (side note: I think that it is a poor choice that the book authors made when selecting to use these meaningless aliases):
Since we are headed on a bit of a tangent, let’s continue a bit further. Start up two SQL*Plus sessions. In session 1 we will execute the following, which creates table T1, truncates the table, returns the OBJECT_ID and DATA_OBJECT_ID, and then returns the SID for session 1:
The output of the above follows:
In session 2 we will prepare to execute the following SQL statement:
In session 1, let’s insert 500 copies of the data found in DBA_OBJECTS into table T1:
In session 2, repeatedly execute the SQL statement that returns the ROW_WAIT_OBJ# and EVENT from V$SESSION. This is the output I received (after eliminating a lot of duplicates):
All of the above wait event entries are reporting 90125 for the ROW_WAIT_OBJ#, which as shown above is the OBJECT_ID. Let’s continue in session 1:
Back in session 2, again checking to see the EVENT and ROW_WAIT_OBJ# for session 1 (again removing many duplicates):
The number 90125 still appears, rather than the DATA_OBJECT_ID value 90126.
We still need to determine if the buffer busy waits wait event places the DATA_OBJECT_ID or the OBJECT_ID into the ROW_WAIT_OBJ# column of V$SESSION – is that wait event special in that it appears to be the only wait event other than db file scattered read that shows the DATA_OBJECT_ID in the ROW_WAIT_OBJ# column (oh wait, I think that I just demonstrated that the documentation is wrong about the db file scattered read wait event)?
Oops – sorry, I missed the “buffer busy waits” part completely 😦
Let me completely change my misguided first comment: I didn’t know that ROW_WAIT_OBJ# was useful for anything other than enqueue waits – thanks a lot for that!
Now that I skimmed that chapter (10) of the 11.2 Performance Tuning guide, I must note that – technically – you didn’t demonstrate the documentation wrong about the db file scattered read wait event, just wrong about the “db file sequential read” when saying the segment in question may be identified by the same method as with “db file scattered read”. Even if the method works for “db file scattered read”, it obviously doesn’t for “db file sequential read” (as you demonstrated) 😉
As for a “buffer busy waits” testcase I’d just assign a biggish table to a smallish recycle pool, submit two jobs doing full scans for a while, and then do your high-frequency sampling. Of course, that would only give me “read by other session” waits. Hmm… Tricky. I finally see the point of this post 🙂
Flado,
Quite correct, and if someone tried the test case that I posted using Oracle 10g R2 the “direct path read” wait event would be replaced with “db file scattered read”, and might be wondering why their results differed from mine. I should have mentioned that the test case I provided above was executed on 11.2.0.2 (or embedded a 😉 in my last sentence).
I like your last two sentences – the underlying secret for a number of my blog articles is that what seems simple on the surface is anything but simple when you start digging into the details. The alpha copy of the 11g book that I am reading seems to have missed that point about buffer busy waits (regarding the new in 10.1 wait event that you mentioned), and as of section 5-7 is only just scratching the surface of the book topics.
Sometimes it is helpful to drift off in a tangent thought as we did here – it helps me recall related facts.
Charles,
Using my standard “kill_cpu” table:
From another session:
This was 10.2.0.3 – and it’s the object_id.
Jonathan,
Thank you for providing the test case. I was having a bit of difficulty putting together a script that would reliably generate buffer busy waits, and had not yet tried PL/SQL loops.
It appears that the output you provided demonstrates that the Performance Tuning Guide (and the alpha copy of the book that I am reading) needs to have a correction or two. Someone might also want to review the following Metalink (MOS) article and fix the broken logic: Doc ID 102925.1, “Tracing sessions: waiting on an enqueue”
This is a big surprise as in all recent sources (Oracle docs, web, books etc.) I have read that ROW_WAIT_OBJ# = DATA_OBJECT_ID no matter what (The sources didn’t explicitly say so but by not debating what you are I think they implied it). This bring us to my question – How did you suspect this to be the case? What motivated/lead you to challenge this notion and discover the ‘anomaly’? Was it just a coincidence?
Thanks,
Paresh
Paresh,
Good question. Regarding the DATA_OBJECT_ID and OBJECT_ID columns, I recall seeing a comment from Jonathan Lewis a couple of years ago regarding a query that he had seen that selected the OBJ column from SYS.X$BH – that same column is exposed as OBJD in V$BH. He stated something to the effect that the X$BH.OBJ column should be joined to the DATA_OBJECT_ID, and not the OBJECT_ID column when drilling into DBA_OBJECTS. It was that comment several years ago that started to make me suspicious whenever I saw a query using either the DATA_OBJECT_ID or OBJECT_ID columns.
Several years ago I started building a performance tuning tool (or toy: https://hoopercharles.wordpress.com/2009/11/30/toy-project-for-performance-tuning/ ) to help troubleshoot problems that I encountered. I would occasionally search through Metalink looking for helpful performance related articles (see: https://hoopercharles.wordpress.com/2009/12/21/miscellaneous-metalink-performance-articles/ https://hoopercharles.wordpress.com/2009/12/24/miscellaneous-metalink-performance-articles-2/ ) looking for helpful scripts, as well as working through the Performance Tuning Guide for 8i and 10g R2. I recall getting burned by one of the scripts in Metalink – this script should be returning an object name, but it returns nothing. Getting frustrated, I changed DATA_OBJECT_ID to OBJECT_ID and the script magically worked. 🙂
I hit the same problem with the Performance Tuning Guide. In the source code for my performance tuning tool I have the following comment embedded into a SQL statement:
The above SQL statement was intended to investigate the waits found in V$SESSION_WAIT. So, the last time I investigated that SQL statement in the program was in March of 2008 – and the Performance Tuning Guide for 11.2 is still wrong. 🙂
The article linked to at the start of this article shows that I rediscovered the problem in the Performance Tuning Guide in September of 2010:
https://hoopercharles.wordpress.com/2010/09/08/something-is-bugging-me-vsession-and-10046-trace-files-show-object_id-or-data_object_id/
The short answer is: if something does not look exactly right, investigate it – you might surprise yourself with the results.
Hi,
Until now I’ve always seen ‘OBJ#’ (and ‘OBJN’) referring to the OBJECT_ID ,and the DATA_OBJECT_ID being referred by names such as DATAOBJ#, OBJD, OBJ, OBJECT_NUMBER.
I’ve seen that empiric rule being true in dictionary tables, dictionary views, trace, dumps, dbms_xxx packages … but I would be glad to know any exception to that 🙂
Event if documentation is not clear about that, I’m sure that in V$SESSIONS, ROW_WAIT_xxx# are referring to logical objects – segments – and absolute files: ROW_WAIT_OBJ# is the OBJECT_ID, and ROW_WAIT_FILE# is the absolute file number.
If you need to have the corresponding ROWID you need to do the OBJECT_ID->DATA_OBJECT_ID conversion from V$OBJECT and the FILE_ID->RELATIVE_FNO from DBA_DATA_FILES
Unfortunately, OBJECT_ID=DATA_OBJECT_ID at object creation and FILE_ID=RELATIVE_FNO at file creation. I suppose it is for compatibility reason when Oracle introduced them.
But a lot of scripts that do not take care of the distinction seems to work … until objects are moved or truncated, or tablespaces are transported.
Besides the names (‘OBJ#’ and’ ‘OBJN’ for the OBJECT_ID and DATAOBJ#, OBJD, OBJ, OBJECT_NUMBER for the DATA_OBJECT_ID), we can guess the meaning by checking if there are other columns that can help to identify uniquely the object:
Having a DATA_OBJECT_ID is not sufficient to identify the object because 2 different objects can have the same data object id. The DATA_OBJECT_ID is unique only within the same object. So when we see an object id without another way to identify the object, then we can be sure that it is the OBJECT_ID or it would be useless.
In the same way, having a relative file number without a way to identify the tablespace, is useless. So when we see a file id without an identifier for the tablespace, then it must be the absolute file id.
ROW_WAIT_OBJ# cannot be the DATA_OBJECT_ID because there is no other column in V$SESSION that helps to distinguish 2 objects that have the same DATA_OBJECT_ID. In addition, see bug 1646533 that was closed as ‘not a bug’ for this reason.
Regards,
Franck.
Franck,
I appreciate the lengthy description that you provided above.
It appears that you wrote an article a while ago that *almost* answered the question about V$SESSION’s ROW_WAIT_OBJ# column (you described that the OBJECT_ID is found in several other views, but not V$SESSION). I thought that I would link to the article here, because on quick glance it appears to be helpful:
http://knol.google.com/k/oracle-table-lock-modes#