Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING 235 Now, our select statement starts executing and reads row 1, row 2, and so on. At some point while we are in the middle of the query, a transaction moves $400.00 from account 123 to account 987. This transaction does the two updates, but does not commit. The table now looks as shown in Table 7-3. Table 7-3. ACCOUNTS Table During Modifications Row Account Number Account Balance Locked? 1 123 ($500.00) changed to $100.00 X 2 456 $240.25 . . . . . . . . . 342,023 987 ($100.00) changed to $500.00 X So, two of those rows are locked. If anyone tried to update them, that user would be blocked. So far, the behavior we are seeing is more or less consistent across all databases. The difference will be in what happens when the query gets to the locked data. When the query we are executing gets to the block containing the locked row (row 342,023) at the “bottom” of the table, it will notice that the data in the row has changed since the time at which it started execution. To provide a consistent (correct) answer, Oracle will at this point create a copy of the block containing this row as it existed when the query began. That is, it will read a value of $100.00, which is the value that existed at the time the query began. Effectively, Oracle takes a detour around the modified data—it reads around it, reconstructing it from the undo (also known as a rollback) segment (discussed in detail in Chapter 9). A consistent and correct answer comes back without waiting for the transaction to commit. Now, a database that allowed a dirty read would simply return the value it saw in account 987 at the time it read it, in this case $500.00. The query would count the transferred $400 twice. Therefore, it not only returns the wrong answer, but also returns a total that never existed in the table at any point in time. In a multiuser database, a dirty read can be a dangerous feature and, personally, I have never seen the usefulness of it. Say that, rather than transferring, the transaction was actually just depositing $400.00 in account 987. The dirty read would count the $400.00 and get the “right” answer, wouldn’t it? Well, suppose the uncommitted transaction was rolled back. We have just counted $400.00 that was never actually in the database. The point here is that dirty read is not a feature; rather, it is a liability. In Oracle, it is just not needed. You get all of the advantages of a dirty read (no blocking) without any of the incorrect results. READ COMMITTED The READ COMMITTED isolation level states that a transaction may only read data that has been committed in the database. There are no dirty reads. There may be nonrepeatable reads (i.e., rereads of the same row may return a different answer in the same transaction) and phantom reads (i.e., newly inserted and committed rows become visible to a query that were not visible earlier in the transaction). READ COMMITTED is perhaps the most commonly used isolation level in database applications everywhere, and it is the default mode for Oracle databases. It is rare to see a different isolation level used.
236 CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING However, achieving READ COMMITTED isolation is not as cut-and-dried as it sounds. If you look at Table 7-1, it appears straightforward. Obviously, given the earlier rules, a query executed in any database using the READ COMMITTED isolation will behave in the same way, will it not? It will not. If you query multiple rows in a single statement then, in almost every other database, READ COMMITTED isolation can be as bad as a dirty read, depending on the implementation. In Oracle, using multi-versioning and read-consistent queries, the answer we get from the ACCOUNTS query is the same in READ COMMITTED as it was in the READ UNCOMMITTED example. Oracle will reconstruct the modified data as it appeared when the query began, returning the answer that was in the database when the query started. Let’s now take a look at how our previous example might work in READ COMMITTED mode in other databases—you might find the answer surprising. We’ll pick up our example at the point described in the previous table: • We are in the middle of the table. We have read and summed the first N rows. • The other transaction has moved $400.00 from account 123 to account 987. • The transaction has not yet committed, so rows containing the information for accounts 123 and 987 are locked. We know what happens in Oracle when it gets to account 987—it will read around the modified data, find out it should be $100.00, and complete. Table 7-4 shows how another database, running in some default READ COMMITTED mode, might arrive at the answer. Table 7-4. Timeline in a Non-Oracle Database Using READ COMMITTED Isolation Time Query Account Transfer Transaction T1 Reads row 1. Sum = $500.00 so far. T2 Reads row 2. Sum = $740.25 so far. T3 Updates row 1 and puts an exclusive lock on row 1, preventing other updates and reads. Row 1 now has $100.00. T4 Reads row N. Sum = . . . T5 Updates row 342,023 and puts an exclusive lock on this row. Row 342,023 now has $500.00. T6 Tries to read row 342,023 and discovers that it is locked. This session will block and wait for this block to become available. All processing on this query stops. T7 Commits transaction. T8 Reads row 342,023, sees $500.00, and presents a final answer that includes the $400.00 double-counted. The first thing to notice is that this other database, upon getting to account 987, will block our query. This session must wait on that row until the transaction holding the exclusive lock
- 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 258 and 259: 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 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 --
- Page 308 and 309: CHAPTER 8 ■ TRANSACTIONS 263 “s
- Page 310 and 311: CHAPTER 8 ■ TRANSACTIONS 265 busi
- Page 312 and 313: CHAPTER 8 ■ TRANSACTIONS 267 Many
- Page 314 and 315: CHAPTER 8 ■ TRANSACTIONS 269 ops$
- Page 316 and 317: CHAPTER 8 ■ TRANSACTIONS 271 last
- Page 318 and 319: CHAPTER 8 ■ TRANSACTIONS 273 Dist
- Page 320 and 321: CHAPTER 8 ■ TRANSACTIONS 275 Auto
- Page 322 and 323: CHAPTER 8 ■ TRANSACTIONS 277 3 Au
- Page 324 and 325: CHAPTER 8 ■ TRANSACTIONS 279 5 pr
- Page 326: CHAPTER 8 ■ TRANSACTIONS 281 scot
- Page 329 and 330: 284 CHAPTER 9 ■ REDO AND UNDO cri
CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING 235<br />
Now, our select statement starts executing <strong>and</strong> reads row 1, row 2, <strong>and</strong> so on. At some<br />
point while we are in the middle of the query, a transaction moves $400.00 from account 123<br />
to account 987. This transaction does the two updates, but does not commit. The table now<br />
looks as shown in Table 7-3.<br />
Table 7-3. ACCOUNTS Table During Modifications<br />
Row Account Number Account Balance Locked?<br />
1 123 ($500.00) changed to $100.00 X<br />
2 456 $240.25<br />
. . . . . . . . .<br />
342,023 987 ($100.00) changed to $500.00 X<br />
So, two of those rows are locked. If anyone tried to update them, that user would be<br />
blocked. So far, the behavior we are seeing is more or less consistent across all databases.<br />
The difference will be in what happens when the query gets to the locked data.<br />
When the query we are executing gets to the block containing the locked row (row<br />
342,023) at the “bottom” of the table, it will notice that the data in the row has changed since<br />
the time at which it started execution. To provide a consistent (correct) answer, <strong>Oracle</strong> will at<br />
this point create a copy of the block containing this row as it existed when the query began.<br />
That is, it will read a value of $100.00, which is the value that existed at the time the query<br />
began. Effectively, <strong>Oracle</strong> takes a detour around the modified data—it reads around it, reconstructing<br />
it from the undo (also known as a rollback) segment (discussed in detail in Chapter 9).<br />
A consistent <strong>and</strong> correct answer comes back without waiting for the transaction to commit.<br />
Now, a database that allowed a dirty read would simply return the value it saw in account<br />
987 at the time it read it, in this case $500.00. The query would count the transferred $400<br />
twice. Therefore, it not only returns the wrong answer, but also returns a total that never<br />
existed in the table at any point in time. In a multiuser database, a dirty read can be a dangerous<br />
feature <strong>and</strong>, personally, I have never seen the usefulness of it. Say that, rather than<br />
transferring, the transaction was actually just depositing $400.00 in account 987. The dirty<br />
read would count the $400.00 <strong>and</strong> get the “right” answer, wouldn’t it? Well, suppose the<br />
uncommitted transaction was rolled back. We have just counted $400.00 that was never<br />
actually in the database.<br />
The point here is that dirty read is not a feature; rather, it is a liability. In <strong>Oracle</strong>, it is just<br />
not needed. You get all of the advantages of a dirty read (no blocking) without any of the incorrect<br />
results.<br />
READ COMMITTED<br />
The READ COMMITTED isolation level states that a transaction may only read data that has been<br />
committed in the database. There are no dirty reads. There may be nonrepeatable reads (i.e.,<br />
rereads of the same row may return a different answer in the same transaction) <strong>and</strong> phantom<br />
reads (i.e., newly inserted <strong>and</strong> committed rows become visible to a query that were not visible<br />
earlier in the transaction). READ COMMITTED is perhaps the most commonly used isolation level<br />
in database applications everywhere, <strong>and</strong> it is the default mode for <strong>Oracle</strong> databases. It is rare<br />
to see a different isolation level used.