A reader of this blog, VijayS, asked me to share the script I use to demo ITL deadlocks that I mentioned in this comment. Since other readers might be interested, here is the script.
SET TERMOUT ON FEEDBACK ON VERIFY OFF SCAN ON ECHO ON
@connect
SELECT * FROM v$version WHERE rownum = 1;
REM
REM cleanup
REM
DROP TABLE t PURGE;
PAUSE
REM
REM create a test table with three completely full data blocks
REM (default tablespace is expected to have 8KB blocks)
REM
CREATE TABLE t (n NUMBER, c VARCHAR2(4000)) PCTFREE 0;
INSERT INTO t SELECT rownum, rpad('*',2679,'*') FROM dual CONNECT BY level <= 9;
COMMIT;
SELECT dbms_rowid.rowid_block_number(rowid), n
FROM t
ORDER BY n;
PAUSE
REM
REM in this session modify two rows: one in the first block and one in the
REM third block
REM
SET SQLPROMPT " 1 > "
SELECT sid FROM v$session WHERE audsid = userenv('sessionid');
UPDATE t SET n=n*10 WHERE n IN (1,7);
PAUSE
REM
REM in another session (called session #2) modify two rows: one in the first
REM block and one in the second block
REM
REM @connect
REM SET SQLPROMPT " 2 > "
REM
REM SELECT sid FROM v$session WHERE audsid = userenv('sessionid');
REM UPDATE t SET n=n*10 WHERE n IN (2,5);
REM
PAUSE
REM
REM in another session (called session #3) try to modify one row per block;
REM since all ITL slots of the first block are taken, wait...
REM
REM @connect
REM SET SQLPROMPT " 3 > "
REM
REM SELECT sid FROM v$session WHERE audsid = userenv('sessionid');
REM UPDATE t SET n=n*10 WHERE n = 9;
REM UPDATE t SET n=n*10 WHERE n = 6;
REM UPDATE t SET n=n*10 WHERE n = 3;
REM
PAUSE
REM
REM in this session try to modify one row in the second block and, in addition,
REM in session #2, try to modify one row in the third block; since all ITL slots
REM of the second and third block are taken, wait..., deadlock...
REM
REM run "UPDATE t SET n=n*10 WHERE n = 8;" in session #2
UPDATE t SET n=n*10 WHERE n = 4;
Notice that:
- the remarks contained in the script provide important information for understanding what the script does and, as a result, for being able to produce a ITL deadlock
- to run the script three sessions are required (when running the script I copy/paste the commands from the output of the terminal running the script to the other two terminals)
To give you an example of what it looks like when you run it, here is a recording:
The deadlock graph generated by the run that I recorded is the following one. Notice that the rows waited on are set to “no row”.
---------Blocker(s)-------- ---------Waiter(s)--------- Resource Name process session holds waits process session holds waits TX-00090013-00001b44 25 140 X 23 147 S TX-0007001d-000019a9 23 147 X 25 140 S session 140: DID 0001-0019-00000D23 session 147: DID 0001-0017-000004BC session 147: DID 0001-0017-000004BC session 140: DID 0001-0019-00000D23 Rows waited on: Session 140: no row Session 147: no row

