Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 6 ■ LOCKING AND LATCHING 213 ops$tkyte@ORA10G> select XIDUSN, XIDSLOT, XIDSQN 2 from v$transaction; XIDUSN XIDSLOT XIDSQN ---------- ---------- ---------- 5 34 1759 4 12 16582 What we see here is that a new transaction has begun, with a transaction ID of (5,34,1759). Our new session, SID=144, has two rows in V$LOCK this time. One row represents the locks that it owns (where LMODE=6). It also has a row in there that shows a REQUEST with a value of 6. This is a request for an exclusive lock. The interesting thing to note here is that the RBS/SLOT/SEQ values of this request row are the transaction ID of the holder of the lock. The transaction with SID=145 is blocking the transaction with SID=144. We can see this more explicitly simply by doing a self-join of V$LOCK: ops$tkyte@ORA10G> select 2 (select username from v$session where sid=a.sid) blocker, 3 a.sid, 4 ' is blocking ', 5 (select username from v$session where sid=b.sid) blockee, 6 b.sid 7 from v$lock a, v$lock b 8 where a.block = 1 9 and b.request > 0 10 and a.id1 = b.id1 11 and a.id2 = b.id2; BLOCKER SID 'ISBLOCKING' BLOCKEE SID --------- ---- ------------- --------- ---- OPS$TKYTE 145 is blocking OPS$TKYTE 144 Now, if we commit our original transaction, SID=145, and rerun our lock query, we find that the request row has gone: ops$tkyte@ORA10G> select username, 2 v$lock.sid, 3 trunc(id1/power(2,16)) rbs, 4 bitand(id1,to_number('ffff','xxxx'))+0 slot, 5 id2 seq, 6 lmode, 7 request 8 from v$lock, v$session 9 where v$lock.type = 'TX' 10 and v$lock.sid = v$session.sid 11 and v$session.username = USER;
214 CHAPTER 6 ■ LOCKING AND LATCHING USERNAME SID RBS SLOT SEQ LMODE REQUEST --------- ---- --- ---- ------ ----- ------- OPS$TKYTE 144 5 34 1759 6 0 ops$tkyte@ORA10G> select XIDUSN, XIDSLOT, XIDSQN 2 from v$transaction; XIDUSN XIDSLOT XIDSQN ---------- ---------- ---------- 5 34 1759 The request row disappeared the instant the other session gave up its lock. That request row was the queuing mechanism. The database is able to wake up the blocked sessions the instant the transaction is completed. There are infinitely more “pretty” displays with various GUI tools, but in a pinch, having knowledge of the tables you need to look at is very useful. However, before we can say that we have a good understanding of how the row locking in Oracle works, we must look at one last topic: how the locking and transaction information is managed with the data itself. It is part of the block overhead. In Chapter 9, we’ll get into the details of the block format, but suffice it to say that at the top of a database block is some leading “overhead” space in which to store a transaction table for that block. This transaction table contains an entry for each “real” transaction that has locked some data in that block. The size of this structure is controlled by two physical attribute parameters on the CREATE statement for an object: • INITRANS: The initial, preallocated size of this structure. This defaults to 2 for indexes and tables (regardless of what Oracle SQL Reference says, I have filed the documentation bug regarding that). • MAXTRANS: The maximum size to which this structure may grow. It defaults to 255 and has a minimum of 2, practically. In Oracle 10g, this setting has been deprecated, so it no longer applies. MAXTRANS is 255 regardless in that release. Each block starts life with, by default, two transaction slots. The number of simultaneous active transactions that a block can ever have is constrained by the value of MAXTRANS and by the availability of space on the block. You may not be able to achieve 255 concurrent transactions on the block if there is not sufficient space to grow this structure. We can artificially demonstrate how this works by creating a table with a constrained MAXTRANS. We’ll need to use Oracle9i or before for this, since in Oracle 10g MAXTRANS is ignored. In Oracle 10g, even if MAXTRANS is set, Oracle will grow the transaction table, as long as there is room on the block to do so. In Oracle9i and before, once the MAXTRANS value is reached for that block, the transaction table will not grow, for example: ops$tkyte@ORA9IR2> create table t ( x int ) maxtrans 2; Table created. ops$tkyte@ORA9IR2> insert into t select rownum from all_users; 24 rows created.
- Page 208 and 209: CHAPTER 5 ■ ORACLE PROCESSES 163
- Page 210 and 211: CHAPTER 5 ■ ORACLE PROCESSES 165
- Page 212 and 213: CHAPTER 5 ■ ORACLE PROCESSES 167
- Page 214 and 215: CHAPTER 5 ■ ORACLE PROCESSES 169
- Page 216 and 217: CHAPTER 5 ■ ORACLE PROCESSES 171
- Page 218 and 219: CHAPTER 5 ■ ORACLE PROCESSES 173
- Page 220 and 221: CHAPTER 5 ■ ORACLE PROCESSES 175
- Page 222 and 223: CHAPTER 5 ■ ORACLE PROCESSES 177
- Page 224 and 225: CHAPTER 5 ■ ORACLE PROCESSES 179
- Page 226 and 227: CHAPTER 5 ■ ORACLE PROCESSES 181
- Page 228 and 229: CHAPTER 6 ■ ■ ■ Locking and L
- Page 230 and 231: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 232 and 233: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 234 and 235: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 236 and 237: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 238 and 239: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 240 and 241: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 242 and 243: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 244 and 245: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 246 and 247: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 248 and 249: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 250 and 251: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 252 and 253: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 254 and 255: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 256 and 257: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 260 and 261: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 262 and 263: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 264 and 265: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 266 and 267: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 268 and 269: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 270 and 271: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 272 and 273: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 274 and 275: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 276 and 277: CHAPTER 7 ■ ■ ■ Concurrency a
- Page 278 and 279: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 280 and 281: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 282 and 283: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 284 and 285: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 286 and 287: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 288 and 289: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 290 and 291: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 292 and 293: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 294 and 295: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 296 and 297: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 298 and 299: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 300 and 301: CHAPTER 8 ■ ■ ■ Transactions
- Page 302 and 303: CHAPTER 8 ■ TRANSACTIONS 257 •
- Page 304 and 305: CHAPTER 8 ■ TRANSACTIONS 259 So,
- Page 306 and 307: CHAPTER 8 ■ TRANSACTIONS 261 X --
CHAPTER 6 ■ LOCKING AND LATCHING 213<br />
ops$tkyte@ORA10G> select XIDUSN, XIDSLOT, XIDSQN<br />
2 from v$transaction;<br />
XIDUSN XIDSLOT XIDSQN<br />
---------- ---------- ----------<br />
5 34 1759<br />
4 12 16582<br />
What we see here is that a new transaction has begun, with a transaction ID of<br />
(5,34,1759). Our new session, SID=144, has two rows in V$LOCK this time. One row represents<br />
the locks that it owns (where LMODE=6). It also has a row in there that shows a REQUEST with a<br />
value of 6. This is a request for an exclusive lock. The interesting thing to note here is that the<br />
RBS/SLOT/SEQ values of this request row are the transaction ID of the holder of the lock. The<br />
transaction with SID=145 is blocking the transaction with SID=144. We can see this more explicitly<br />
simply by doing a self-join of V$LOCK:<br />
ops$tkyte@ORA10G> select<br />
2 (select username from v$session where sid=a.sid) blocker,<br />
3 a.sid,<br />
4 ' is blocking ',<br />
5 (select username from v$session where sid=b.sid) blockee,<br />
6 b.sid<br />
7 from v$lock a, v$lock b<br />
8 where a.block = 1<br />
9 <strong>and</strong> b.request > 0<br />
10 <strong>and</strong> a.id1 = b.id1<br />
11 <strong>and</strong> a.id2 = b.id2;<br />
BLOCKER SID 'ISBLOCKING' BLOCKEE SID<br />
--------- ---- ------------- --------- ----<br />
OPS$TKYTE 145 is blocking OPS$TKYTE 144<br />
Now, if we commit our original transaction, SID=145, <strong>and</strong> rerun our lock query, we find<br />
that the request row has gone:<br />
ops$tkyte@ORA10G> select username,<br />
2 v$lock.sid,<br />
3 trunc(id1/power(2,16)) rbs,<br />
4 bit<strong>and</strong>(id1,to_number('ffff','xxxx'))+0 slot,<br />
5 id2 seq,<br />
6 lmode,<br />
7 request<br />
8 from v$lock, v$session<br />
9 where v$lock.type = 'TX'<br />
10 <strong>and</strong> v$lock.sid = v$session.sid<br />
11 <strong>and</strong> v$session.username = USER;