Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 9 ■ REDO AND UNDO 295 • We’ve obviously increased the round-trips to and from the database. If we commit every record, we are generating that much more traffic back and forth. • Every time we commit, we must wait for our redo to be written to disk. This will result in a “wait.” In this case, the wait is named “log file sync.” We can actually observe the latter easily by slightly modifying the Java application. We’ll do two things: • Add a call to DBMS_MONITOR to enable SQL tracing with wait events. In Oracle9i, we would use alter session set events '10046 trace name context forever, level 12' instead, as DBMS_MONITOR is new in Oracle 10g. • Change the con.commit() call to be a call to a SQL statement to perform the commit. If you use the built-in JDBC commit() call, this does not emit a SQL COMMIT statement to the trace file, and TKPROF, the tool used to format a trace file, will not report the time spent doing the COMMIT. So, we modify the doInserts() method as follows: doInserts( con, 1, 1 ); Statement stmt = con.createStatement (); stmt.execute ( "begin dbms_monitor.session_trace_enable(waits=>TRUE); end;" ); doInserts( con, iters.intValue(), iters.intValue() ); To the main method, we add the following: PreparedStatement commit = con.prepareStatement ("begin /* commit size = " + commitCount + " */ commit; end;" ); int rowcnt = 0; int committed = 0; ... if ( rowcnt == commitCount ) { commit.executeUpdate(); rowcnt = 0; committed++; Upon running that application with 10,000 rows to insert, committing every row, the TKPROF report would show results similar to the following: begin /* commit size = 1 */ commit; end; .... Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ SQL*Net message to client 10000 0.00 0.01 SQL*Net message from client 10000 0.00 0.04 log file sync 8288 0.06 2.00
296 CHAPTER 9 ■ REDO AND UNDO If we insert 10,000 rows and only commit when all 10,000 are inserted, we get results similar to the following: begin /* commit size = 10000 */ commit; end; .... Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ log file sync 1 0.00 0.00 SQL*Net message to client 1 0.00 0.00 SQL*Net message from client 1 0.00 0.00 When we committed after every INSERT, we waited almost every time—and if you wait a little bit of time but you wait often, then it all adds up. Fully two seconds of our runtime was spent waiting for a COMMIT to complete—in other words, waiting for LGWR to write the redo to disk. In stark contrast, when we committed once, we didn’t wait very long (not a measurable amount of time actually). This proves that a COMMIT is a fast operation; we expect the response time to be more or less flat, not a function of the amount of work we’ve done. So, why is a COMMIT’s response time fairly flat, regardless of the transaction size? Before we even go to COMMIT in the database, we’ve already done the really hard work. We’ve already modified the data in the database, so we’ve already done 99.9 percent of the work. For example, operations such as the following have already taken place: • Undo blocks have been generated in the SGA. • Modified data blocks have been generated in the SGA. • Buffered redo for the preceding two items has been generated in the SGA. • Depending on the size of the preceding three items, and the amount of time spent, some combination of the previous data may be flushed onto disk already. • All locks have been acquired. When we COMMIT, all that is left to happen is the following: • An SCN is generated for our transaction. In case you are not familiar with it, the SCN is a simple timing mechanism Oracle uses to guarantee the ordering of transactions and to enable recovery from failure. It is also used to guarantee read-consistency and checkpointing in the database. Think of the SCN as a ticker; every time someone COMMITs, the SCN is incremented by one. • LGWR writes all of our remaining buffered redo log entries to disk and records the SCN in the online redo log files as well. This step is actually the COMMIT. If this step occurs, we have committed. Our transaction entry is “removed” from V$TRANSACTION—this shows that we have committed. • All locks recorded in V$LOCK held by our session are released, and everyone who was enqueued waiting on locks we held will be woken up and allowed to proceed with their work.
- 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
- Page 331 and 332: 286 CHAPTER 9 ■ REDO AND UNDO Fir
- Page 333 and 334: 288 CHAPTER 9 ■ REDO AND UNDO The
- Page 335 and 336: 290 CHAPTER 9 ■ REDO AND UNDO We
- Page 337 and 338: 292 CHAPTER 9 ■ REDO AND UNDO Wha
- Page 339: 294 CHAPTER 9 ■ REDO AND UNDO row
- Page 343 and 344: 298 CHAPTER 9 ■ REDO AND UNDO ops
- Page 345 and 346: 300 CHAPTER 9 ■ REDO AND UNDO Inv
- Page 347 and 348: 302 CHAPTER 9 ■ REDO AND UNDO The
- Page 349 and 350: 304 CHAPTER 9 ■ REDO AND UNDO 41
- Page 351 and 352: 306 CHAPTER 9 ■ REDO AND UNDO ins
- Page 353 and 354: 308 CHAPTER 9 ■ REDO AND UNDO So,
- Page 355 and 356: 310 CHAPTER 9 ■ REDO AND UNDO ops
- Page 357 and 358: 312 CHAPTER 9 ■ REDO AND UNDO ops
- Page 359 and 360: 314 CHAPTER 9 ■ REDO AND UNDO •
- Page 361 and 362: 316 CHAPTER 9 ■ REDO AND UNDO ...
- Page 363 and 364: 318 CHAPTER 9 ■ REDO AND UNDO •
- Page 365 and 366: 320 CHAPTER 9 ■ REDO AND UNDO bac
- Page 367 and 368: 322 CHAPTER 9 ■ REDO AND UNDO As
- Page 369 and 370: 324 CHAPTER 9 ■ REDO AND UNDO ops
- Page 371 and 372: 326 CHAPTER 9 ■ REDO AND UNDO wil
- Page 373 and 374: 328 CHAPTER 9 ■ REDO AND UNDO Thi
- Page 375 and 376: 330 CHAPTER 9 ■ REDO AND UNDO ops
- Page 377 and 378: 332 CHAPTER 9 ■ REDO AND UNDO Whe
- Page 379 and 380: 334 CHAPTER 9 ■ REDO AND UNDO Tha
- Page 381 and 382: 336 CHAPTER 9 ■ REDO AND UNDO tou
- Page 383 and 384: 338 CHAPTER 10 ■ DATABASE TABLES
- Page 385 and 386: 340 CHAPTER 10 ■ DATABASE TABLES
- Page 387 and 388: 342 CHAPTER 10 ■ DATABASE TABLES
- Page 389 and 390: 344 CHAPTER 10 ■ DATABASE TABLES
CHAPTER 9 ■ REDO AND UNDO 295<br />
• We’ve obviously increased the round-trips to <strong>and</strong> from the database. If we commit<br />
every record, we are generating that much more traffic back <strong>and</strong> forth.<br />
• Every time we commit, we must wait for our redo to be written to disk. This will result<br />
in a “wait.” In this case, the wait is named “log file sync.”<br />
We can actually observe the latter easily by slightly modifying the Java application. We’ll<br />
do two things:<br />
• Add a call to DBMS_MONITOR to enable SQL tracing with wait events. In <strong>Oracle</strong>9i, we would<br />
use alter session set events '10046 trace name context forever, level 12'<br />
instead, as DBMS_MONITOR is new in <strong>Oracle</strong> 10g.<br />
• Change the con.commit() call to be a call to a SQL statement to perform the commit.<br />
If you use the built-in JDBC commit() call, this does not emit a SQL COMMIT statement<br />
to the trace file, <strong>and</strong> TKPROF, the tool used to format a trace file, will not report the time<br />
spent doing the COMMIT.<br />
So, we modify the doInserts() method as follows:<br />
doInserts( con, 1, 1 );<br />
Statement stmt = con.createStatement ();<br />
stmt.execute<br />
( "begin dbms_monitor.session_trace_enable(waits=>TRUE); end;" );<br />
doInserts( con, iters.intValue(), iters.intValue() );<br />
To the main method, we add the following:<br />
PreparedStatement commit =<br />
con.prepareStatement<br />
("begin /* commit size = " + commitCount + " */ commit; end;" );<br />
int rowcnt = 0;<br />
int committed = 0;<br />
...<br />
if ( rowcnt == commitCount )<br />
{<br />
commit.executeUpdate();<br />
rowcnt = 0;<br />
committed++;<br />
Upon running that application with 10,000 rows to insert, committing every row, the<br />
TKPROF report would show results similar to the following:<br />
begin /* commit size = 1 */ commit; end;<br />
....<br />
Elapsed times include waiting on following events:<br />
Event waited on Times Max. Wait Total Waited<br />
---------------------------------------- Waited ---------- ------------<br />
SQL*Net message to client 10000 0.00 0.01<br />
SQL*Net message from client 10000 0.00 0.04<br />
log file sync 8288 0.06 2.00