1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Chapter 3. Transaction Basics</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /> 9 <link rel="home" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" /> 10 <link rel="up" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" /> 11 <link rel="previous" href="envopen.html" title="Opening a Transactional Environment and Database " /> 12 <link rel="next" href="abortresults.html" title="Aborting a Transaction" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Chapter 3. Transaction Basics</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="envopen.html">Prev</a> </td> 22 <th width="60%" align="center"> </th> 23 <td width="20%" align="right"> <a accesskey="n" href="abortresults.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="chapter" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title"><a id="usingtxns"></a>Chapter 3. Transaction Basics</h2> 33 </div> 34 </div> 35 <div></div> 36 </div> 37 <div class="toc"> 38 <p> 39 <b>Table of Contents</b> 40 </p> 41 <dl> 42 <dt> 43 <span class="sect1"> 44 <a href="usingtxns.html#commitresults">Committing a Transaction</a> 45 </span> 46 </dt> 47 <dd> 48 <dl> 49 <dt> 50 <span class="sect2"> 51 <a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a> 52 </span> 53 </dt> 54 </dl> 55 </dd> 56 <dt> 57 <span class="sect1"> 58 <a href="abortresults.html">Aborting a Transaction</a> 59 </span> 60 </dt> 61 <dt> 62 <span class="sect1"> 63 <a href="autocommit.html">Auto Commit</a> 64 </span> 65 </dt> 66 <dt> 67 <span class="sect1"> 68 <a href="nestedtxn.html">Nested Transactions</a> 69 </span> 70 </dt> 71 <dt> 72 <span class="sect1"> 73 <a href="txncursor.html">Transactional Cursors</a> 74 </span> 75 </dt> 76 <dt> 77 <span class="sect1"> 78 <a href="txnindices.html">Secondary Indices with Transaction Applications</a> 79 </span> 80 </dt> 81 <dt> 82 <span class="sect1"> 83 <a href="maxtxns.html">Configuring the Transaction Subsystem</a> 84 </span> 85 </dt> 86 </dl> 87 </div> 88 <p> 89 Once you have enabled transactions for your environment and your databases, 90 you can use them to protect your database operations. You do this by 91 acquiring a transaction handle and then using that handle for any 92 database operation that you want to participate in that transaction. 93 </p> 94 <p> 95 You obtain a transaction handle using the 96 97 <span><tt class="methodname">DbEnv::txn_begin()</tt> method.</span> 98 99 100 101 </p> 102 <p> 103 Once you have completed all of the operations that you want to include 104 in the transaction, you must commit the transaction using the 105 106 <span><tt class="methodname">DbTxn::commit()</tt> method.</span> 107 108 109 110 111 </p> 112 <p> 113 If, for any reason, you want to abandon the transaction, you abort 114 it using 115 116 <span><tt class="methodname">DbTxn::abort()</tt>.</span> 117 118 119 120 121 122 </p> 123 <p> 124 Any transaction handle that has been committed or aborted can no longer 125 be used by your application. 126 </p> 127 <p> 128 Finally, you must make sure that all transaction handles are either 129 committed or aborted before closing your databases and environment. 130 </p> 131 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 132 <h3 class="title">Note</h3> 133 <p> 134 If you only want to transaction protect a single database write operation, you can use auto commit to 135 perform the transaction administration. When you use auto commit, you do not need an explicit transaction 136 handle. See <a href="autocommit.html">Auto Commit</a> for more information. 137 </p> 138 </div> 139 <p> 140 For example, the following example opens a transactional-enabled environment and 141 database, obtains a transaction handle, and then performs a write 142 operation under its protection. In the event of any failure in the 143 write operation, the transaction is aborted and the database is left in a 144 state as if no operations had ever been attempted in the first place. 145 </p> 146 <pre class="programlisting">#include "db_cxx.h" 147 148... 149 150int main(void) 151{ 152 u_int32_t env_flags = DB_CREATE | // If the environment does not 153 // exist, create it. 154 DB_INIT_LOCK | // Initialize locking 155 DB_INIT_LOG | // Initialize logging 156 DB_INIT_MPOOL | // Initialize the cache 157 DB_INIT_TXN; // Initialize transactions 158 159 u_int32_t db_flags = DB_CREATE | DB_AUTO_COMMIT; 160 Db *dbp = NULL; 161 const char *file_name = "mydb.db"; 162 const char *keystr ="thekey"; 163 const char *datastr = "thedata"; 164 165 std::string envHome("/export1/testEnv"); 166 DbEnv myEnv(0); 167 168 try { 169 170 myEnv.open(envHome.c_str(), env_flags, 0); 171 dbp = new Db(&myEnv, 0); 172 173 // Open the database. Note that we are using auto commit for 174 // the open, so the database is able to support transactions. 175 dbp->open(NULL, // Txn pointer 176 file_name, // File name 177 NULL, // Logical db name 178 DB_BTREE, // Database type (using btree) 179 db_flags, // Open flags 180 0); // File mode. Using defaults 181 182 Dbt key, data; 183 key.set_data(keystr); 184 key.set_size((strlen(keystr) + 1) * sizeof(char)); 185 key.set_data(datastr); 186 key.set_size((strlen(datastr) + 1) * sizeof(char)); 187 188 DbTxn *txn = NULL; 189 myEnv.txn_begin(NULL, &txn, 0); 190 try { 191 db->put(txn, &key, &data, 0); 192 txn->commit(0); 193 } catch (DbException &e) { 194 std::cerr << "Error in transaction: " 195 << e.what() << std::endl; 196 txn->abort(); 197 } 198 199 } catch(DbException &e) { 200 std::cerr << "Error opening database and environment: " 201 << file_name << ", " 202 << envHome << std::endl; 203 std::cerr << e.what() << std::endl; 204 } 205 206 try { 207 if (dbp != NULL) 208 dbp->close(0); 209 myEnv.close(0); 210 } catch(DbException &e) { 211 std::cerr << "Error closing database and environment: " 212 << file_name << ", " 213 << envHome << std::endl; 214 std::cerr << e.what() << std::endl; 215 return (EXIT_FAILURE); 216 } 217 218 return (EXIT_SUCCESS); 219} </pre> 220 <div class="sect1" lang="en" xml:lang="en"> 221 <div class="titlepage"> 222 <div> 223 <div> 224 <h2 class="title" style="clear: both"><a id="commitresults"></a>Committing a Transaction</h2> 225 </div> 226 </div> 227 <div></div> 228 </div> 229 <p> 230 In order to fully understand what is happening when you commit 231 a transaction, you must first understand a little about what 232 DB is doing with 233 234 <span> 235 the logging subsystem. 236 </span> 237 238 239 240 Logging causes all database write operations to be identified in 241 242 <span>logs, and by default these 243 logs are backed by files on disk. These logs are used to restore your databases 244 245 </span> 246 247 248 249 in the event of a system or application failure, so by performing 250 logging, DB ensures the integrity of your data. 251 </p> 252 <p> 253 Moreover, DB performs <span class="emphasis"><em>write-ahead</em></span> 254 logging. This means that information is written to the logs 255 <span class="emphasis"><em>before</em></span> the actual database 256 257 is changed. 258 This means that all write activity performed under the 259 protection of the transaction is noted in the log before 260 the transaction is committed. Be aware, however, that database 261 maintains logs in-memory. If you are backing your logs on 262 disk, the log information will eventually be written to the log 263 files, but while the transaction is on-going the log data may be 264 held only in memory. 265 </p> 266 <p> 267 When you commit a transaction, the following occurs: 268 </p> 269 <div class="itemizedlist"> 270 <ul type="disc"> 271 <li> 272 <p> 273 A commit record is written to the log. This 274 indicates that the modifications made by the 275 transaction are now permanent. By default, this write is performed synchronously to disk so the 276 commit record arrives in the log files before any other actions are taken. 277 </p> 278 </li> 279 <li> 280 <p> 281 Any log information held in memory is (by default) 282 synchronously written to disk. Note that this requirement can be 283 relaxed, depending on the type of commit you perform. 284 See <a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a> for 285 more information. 286 <span>Also, if you are 287 maintaining your logs entirely in-memory, then this 288 step will of course not be taken. To configure your 289 logging system for in-memory usage, see 290 <a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>. 291 </span> 292 </p> 293 </li> 294 <li> 295 <p> 296 All locks held by the transaction are released. This means 297 that read operations performed by other transactions or 298 threads of control can now see the modifications without 299 resorting to uncommitted reads (see <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a> for more information). 300 </p> 301 </li> 302 </ul> 303 </div> 304 <p> 305 To commit a transaction, you simply call 306 307 <span><tt class="methodname">DbTxn::commit()</tt>.</span> 308 309 310 311 </p> 312 <p> 313 Notice that committing a transaction does not necessarily cause data 314 modified in your memory cache to be written to the files 315 backing your databases on disk. Dirtied database pages are written 316 for a number of reasons, but a transactional 317 commit is not one of them. The following are the things that can cause a dirtied 318 database page to be written to the backing database file: 319 </p> 320 <div class="itemizedlist"> 321 <ul type="disc"> 322 <li> 323 <p> 324 Checkpoints. 325 </p> 326 <p> 327 Checkpoints cause all dirtied pages currently existing 328 in the cache to be written to disk, and a checkpoint 329 record is then written to the logs. You can run checkpoints 330 explicitly. For more information on checkpoints, 331 see <a href="filemanagement.html#checkpoints">Checkpoints</a>. 332 </p> 333 </li> 334 <li> 335 <p> 336 Cache is full. 337 </p> 338 <p> 339 If the in-memory cache fills up, then dirtied pages 340 might be written to disk in order to free up space for other 341 pages that your application needs to use. Note that if 342 dirtied pages are written to the database files, then 343 any log records that describe how those pages were 344 dirtied are written to disk before the database 345 pages are written. 346 </p> 347 </li> 348 </ul> 349 </div> 350 <p> 351 Be aware that because your transaction commit caused database 352 353 modifications recorded in your logs to be forced to disk, your modifications 354 are by default "persistent" in that they can be recovered in the event of 355 an application or system failure. However, recovery time is 356 gated by how much data has been modified since the last 357 checkpoint, so for applications that perform a lot of writes, 358 you may want to run a checkpoint with some frequency. 359 </p> 360 <p> 361 Note that once you have committed a transaction, the transaction 362 handle that you used for the transaction is no longer valid. To 363 perform database activities under the control of a new 364 transaction, you must obtain a fresh transaction handle. 365 </p> 366 <div class="sect2" lang="en" xml:lang="en"> 367 <div class="titlepage"> 368 <div> 369 <div> 370 <h3 class="title"><a id="nodurabletxn"></a>Non-Durable Transactions</h3> 371 </div> 372 </div> 373 <div></div> 374 </div> 375 <p> 376 As previously noted, by default transaction commits are 377 durable because they cause the modifications performed 378 under the transaction to be synchronously recorded in 379 your on-disk log files. However, it is possible to use 380 non-durable transactions. 381 </p> 382 <p> 383 You may want non-durable transactions for performance 384 reasons. For example, you might be using transactions 385 simply for the isolation guarantee. 386 387 <span> 388 In this case, you might 389 not want a durability guarantee and so you may want to 390 prevent the disk I/O that normally accompanies a 391 transaction commit. 392 </span> 393 394 </p> 395 <p> 396 There are several ways to remove the durability guarantee 397 for your transactions: 398 </p> 399 <div class="itemizedlist"> 400 <ul type="disc"> 401 <li> 402 <p> 403 Specify 404 <span> 405 <tt class="literal">DB_TXN_NOSYNC</tt> using the 406 407 <tt class="methodname">DbEnv::set_flags()</tt> 408 method. 409 </span> 410 411 This causes DB to not synchronously force any 412 <span> 413 log 414 </span> 415 data to disk upon transaction commit. 416 417 <span> 418 That is, the modifications are held entirely 419 in the in-memory cache and the logging 420 information is not forced to the filesystem for 421 long-term storage. 422 </span> 423 424 Note, however, that the 425 <span> 426 logging 427 </span> 428 data will eventually make it to the filesystem (assuming no 429 application or OS crashes) as a part of DB's 430 management of its logging buffers and/or cache. 431 </p> 432 <p> 433 This form of a commit provides a weak durability 434 guarantee because data loss can occur due to 435 an application 436 or OS crash. 437 </p> 438 <p> 439 This behavior is specified on a per-environment 440 handle basis. In order for your application to exhibit consistent 441 behavior, you need to specify this 442 <span>flag</span> 443 444 for all of the environment handles used in your application. 445 </p> 446 <p> 447 You can achieve this behavior on a transaction by transaction basis by 448 <span> 449 specifying <tt class="literal">DB_TXN_NOSYNC</tt> to the 450 451 <tt class="methodname">DbTxn::commit()</tt> 452 453 method. 454 </span> 455 456 457 458 </p> 459 </li> 460 <li> 461 <p> 462 Specify 463 <span> 464 <tt class="literal">DB_TXN_WRITE_NOSYNC</tt> using the 465 466 <tt class="methodname">DbEnv::set_flags()</tt> 467 method. 468 </span> 469 470 471 472 This causes 473 <span> 474 logging 475 </span> 476 data to be synchronously 477 written to the OS's file system buffers upon 478 transaction commit. The data will eventually be 479 written to disk, but this occurs when the 480 operating system chooses to schedule the 481 activity; the transaction commit can complete 482 successfully before this disk I/O is performed 483 by the OS. 484 </p> 485 <p> 486 This form of commit protects you against application 487 crashes, but not against OS 488 crashes. This method offers less room for the possibility of data loss than does 489 <span><tt class="literal">DB_TXN_NOSYNC</tt>.</span> 490 491 </p> 492 <p> 493 This behavior is specified on a per-environment 494 handle basis. In order for your application to exhibit consistent 495 behavior, you need to specify this 496 <span>flag</span> 497 498 for all of the environment handles used in your application. 499 </p> 500 </li> 501 <li> 502 <p> 503 Maintain your logs entirely in-memory. In this 504 case, your logs are never written to disk. The 505 result is that you lose all durability guarantees. 506 See 507 <a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a> 508 for more information. 509 </p> 510 </li> 511 </ul> 512 </div> 513 </div> 514 </div> 515 </div> 516 <div class="navfooter"> 517 <hr /> 518 <table width="100%" summary="Navigation footer"> 519 <tr> 520 <td width="40%" align="left"><a accesskey="p" href="envopen.html">Prev</a> </td> 521 <td width="20%" align="center"> 522 <a accesskey="u" href="index.html">Up</a> 523 </td> 524 <td width="40%" align="right"> <a accesskey="n" href="abortresults.html">Next</a></td> 525 </tr> 526 <tr> 527 <td width="40%" align="left" valign="top">Opening a Transactional Environment and 528 Database 529 530 531 </td> 532 <td width="20%" align="center"> 533 <a accesskey="h" href="index.html">Home</a> 534 </td> 535 <td width="40%" align="right" valign="top"> Aborting a Transaction</td> 536 </tr> 537 </table> 538 </div> 539 </body> 540</html> 541