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>Isolation</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="txnconcurrency.html" title="Chapter 4. Concurrency" /> 11 <link rel="previous" href="lockingsubsystem.html" title="The Locking Subsystem" /> 12 <link rel="next" href="txn_ccursor.html" title="Transactional Cursors and Concurrent Applications" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Isolation</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="lockingsubsystem.html">Prev</a> </td> 22 <th width="60%" align="center">Chapter 4. Concurrency</th> 23 <td width="20%" align="right"> <a accesskey="n" href="txn_ccursor.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="isolation"></a>Isolation</h2> 33 </div> 34 </div> 35 <div></div> 36 </div> 37 <p> 38 Isolation guarantees are an important aspect of transactional 39 protection. Transactions 40 ensure the data your transaction is working with will not be changed by some other transaction. 41 Moreover, the modifications made by a transaction will never be viewable outside of that transaction until 42 the changes have been committed. 43 </p> 44 <p> 45 That said, there are different degrees of isolation, and you can choose to relax your isolation 46 guarantees to one degree or another depending on your application's requirements. The primary reason why 47 you might want to do this is because of performance; the more isolation you ask your transactions to 48 provide, the more locking that your application must do. With more locking comes a greater chance of 49 blocking, which in turn causes your threads to pause while waiting for a lock. Therefore, by relaxing 50 your isolation guarantees, you can <span class="emphasis"><em>potentially</em></span> improve your application's throughput. 51 Whether you actually see any improvement depends, of course, on 52 the nature of your application's data and transactions. 53 </p> 54 <div class="sect2" lang="en" xml:lang="en"> 55 <div class="titlepage"> 56 <div> 57 <div> 58 <h3 class="title"><a id="degreesofisolation"></a>Supported Degrees of Isolation</h3> 59 </div> 60 </div> 61 <div></div> 62 </div> 63 <p> 64 DB supports the following levels of isolation: 65 </p> 66 <div class="informaltable"> 67 <table border="1" width="80%"> 68 <colgroup> 69 <col /> 70 <col /> 71 <col /> 72 </colgroup> 73 <thead> 74 <tr> 75 <th>Degree</th> 76 <th>ANSI Term</th> 77 <th>Definition</th> 78 </tr> 79 </thead> 80 <tbody> 81 <tr> 82 <td>1</td> 83 <td>READ UNCOMMITTED</td> 84 <td> 85 Uncommitted reads means that one transaction will never 86 overwrite another transaction's dirty data. Dirty data is 87 data that a transaction has modified but not yet committed 88 to the underlying data store. However, uncommitted reads allows a 89 transaction to see data dirtied by another 90 transaction. In addition, a transaction may read data 91 dirtied by another transaction, but which subsequently 92 is aborted by that other transaction. In this latter 93 case, the reading transaction may be reading data that 94 never really existed in the database. 95 </td> 96 </tr> 97 <tr> 98 <td>2</td> 99 <td>READ COMMITTED</td> 100 <td> 101 <p> 102 Committed read isolation means that degree 1 is observed, except that dirty data is never read. 103 </p> 104 <p> 105 In addition, this isolation level guarantees that data will never change so long as 106 it is addressed by the cursor, but the data may change before the reading cursor is closed. 107 In the case of a transaction, data at the current 108 cursor position will not change, but once the cursor 109 moves, the previous referenced data can change. This 110 means that readers release read locks before the cursor 111 is closed, and therefore, before the transaction 112 completes. Note that this level of isolation causes the 113 cursor to operate in exactly the same way as it does in 114 the absence of a transaction. 115 </p> 116 </td> 117 </tr> 118 <tr> 119 <td>3</td> 120 <td>SERIALIZABLE</td> 121 <td> 122 <p> 123 Committed read is observed, plus the data read by a transaction, T, 124 will never be dirtied by another transaction before T completes. 125 This means that both read and write locks are not 126 released until the transaction completes. 127 </p> 128 <p> 129 <span> 130 In addition, 131 </span> 132 133 134 135 no transactions will see phantoms. Phantoms are records 136 returned as a result of a search, but which were not seen by 137 the same transaction when the identical 138 search criteria was previously used. 139 </p> 140 <p> 141 This is DB's default isolation guarantee. 142 </p> 143 </td> 144 </tr> 145 </tbody> 146 </table> 147 </div> 148 <p> 149 150 By default, DB transactions and transactional cursors offer 151 <span> 152 serializable isolation. 153 </span> 154 155 156 You can optionally reduce your isolation level by configuring DB to use 157 uncommitted read isolation. See 158 <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a> 159 for more information. 160 161 You can also configure DB to use committed read isolation. See 162 <a href="isolation.html#readcommitted">Committed Reads</a> 163 for more information. 164 165 </p> 166 <p> 167 Finally, in addition to DB's normal degrees of isolation, you 168 can also use <span class="emphasis"><em>snapshot isolation</em></span>. This allows 169 you to avoid the read locks that serializable isolation requires. See 170 <a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a> 171 for details. 172 </p> 173 </div> 174 <div class="sect2" lang="en" xml:lang="en"> 175 <div class="titlepage"> 176 <div> 177 <div> 178 <h3 class="title"><a id="dirtyreads"></a>Reading Uncommitted Data</h3> 179 </div> 180 </div> 181 <div></div> 182 </div> 183 <p> 184 You can configure your application to read data that has been modified but not yet 185 committed by another transaction; that is, dirty data. When you do this, you 186 may see a performance benefit by allowing your 187 application to not have to block waiting for write locks. On the other hand, the data that your 188 application is reading may change before the transaction has completed. 189 </p> 190 <p> 191 When used with transactions, uncommitted reads means that one transaction can see data 192 modified but not yet committed by another transaction. When 193 used with transactional cursors, uncommitted reads means 194 that any database reader can see data modified by the 195 cursor before the cursor's transaction has committed. 196 </p> 197 <p> 198 Because of this, uncommitted reads allow a transaction to read data 199 that may subsequently be aborted by another transaction. In 200 this case, the reading transaction will have read data that 201 never really existed in the database. 202 </p> 203 <p> 204 To configure your application to read uncommitted data: 205 </p> 206 <div class="orderedlist"> 207 <ol type="1"> 208 <li> 209 <p> 210 Open your database such that it will allow uncommitted reads. You do this by 211 <span> 212 specifying <tt class="literal">DB_READ_UNCOMMITTED</tt> when you open your database. 213 </span> 214 215 </p> 216 </li> 217 <li> 218 <p> 219 <span> 220 Specify <tt class="literal">DB_READ_UNCOMMITTED</tt> 221 when you create the transaction, 222 <span> 223 open the cursor, or read a record from the database. 224 </span> 225 226 </span> 227 228 229 </p> 230 </li> 231 </ol> 232 </div> 233 <p> 234 For example, the following opens the database such that it supports uncommitted reads, and then creates a 235 transaction that causes all reads performed within it to use uncommitted reads. Remember that simply opening 236 the database to support uncommitted reads is not enough; you must also declare your read operations to be 237 performed using uncommitted reads. 238 </p> 239 <pre class="programlisting">#include <stdio.h> 240#include <stdlib.h> 241 242#include "db.h" 243 244int 245main(void) 246{ 247 int ret, ret_c; 248 u_int32_t db_flags, env_flags; 249 DB *dbp; 250 DB_ENV *envp; 251 DB_TXN *txn; 252 const char *db_home_dir = "/tmp/myEnvironment"; 253 const char *file_name = "mydb.db"; 254 const char *keystr ="thekey"; 255 const char *datastr = "thedata"; 256 257 dbp = NULL; 258 envp = NULL; 259 260 /* Open the environment */ 261 ret = db_env_create(&envp, 0); 262 if (ret != 0) { 263 fprintf(stderr, "Error creating environment handle: %s\n", 264 db_strerror(ret)); 265 return (EXIT_FAILURE); 266 } 267 268 env_flags = DB_CREATE | /* If the environment does not 269 * exist, create it. */ 270 DB_INIT_LOCK | /* Initialize locking */ 271 DB_INIT_LOG | /* Initialize logging */ 272 DB_INIT_MPOOL | /* Initialize the cache */ 273 DB_THREAD | /* Free-thread the env handle. */ 274 DB_INIT_TXN; /* Initialize transactions */ 275 276 ret = envp->open(envp, db_home_dir, env_flags, 0); 277 if (ret != 0) { 278 fprintf(stderr, "Error opening environment: %s\n", 279 db_strerror(ret)); 280 goto err; 281 } 282 283 /* Initialize the DB handle */ 284 ret = db_create(&dbp, envp, 0); 285 if (ret != 0) { 286 envp->err(envp, ret, "Database creation failed"); 287 goto err; 288 } 289 290 db_flags = DB_CREATE | /* Create the db if it does not 291 * exist */ 292 DB_AUTO_COMMIT | /* Enable auto commit */ 293 DB_READ_UNCOMMITTED; /* Enable uncommitted reads */ 294 295 ret = dbp->open(dbp, /* Pointer to the database */ 296 NULL, /* Txn pointer */ 297 file_name, /* File name */ 298 NULL, /* Logical db name */ 299 DB_BTREE, /* Database type (using btree) */ 300 db_flags, /* Open flags */ 301 0); /* File mode. Using defaults */ 302 if (ret != 0) { 303 envp->err(envp, ret, "Database '%s' open failed", 304 file_name); 305 goto err; 306 } 307 308 /* Get the txn handle */ 309 txn = NULL; 310 ret = envp->txn_begin(envp, NULL, &txn, DB_READ_UNCOMMITTED); 311 if (ret != 0) { 312 envp->err(envp, ret, "Transaction begin failed."); 313 goto err; 314 } 315 316 /* 317 * From here, you perform your database reads and writes as normal, 318 * committing and aborting the transactions as is necessary, and 319 * testing for deadlock exceptions as normal (omitted for brevity). 320 */ 321 322 ... </pre> 323 </div> 324 <div class="sect2" lang="en" xml:lang="en"> 325 <div class="titlepage"> 326 <div> 327 <div> 328 <h3 class="title"><a id="readcommitted"></a>Committed Reads</h3> 329 </div> 330 </div> 331 <div></div> 332 </div> 333 <p> 334 You can configure your transaction so that the data being 335 read by a transactional cursor is consistent so long as it 336 is being addressed by the cursor. However, once the cursor is done reading the 337 338 <span> 339 record (that is, reading records from the page that it currently has locked), 340 </span> 341 342 the cursor releases its lock on that 343 344 <span> 345 record or page. 346 </span> 347 348 This means that the data the cursor has read and released 349 may change before the cursor's transaction has completed. 350 </p> 351 <p> 352 For example, 353 suppose you have two transactions, <tt class="literal">Ta</tt> and <tt class="literal">Tb</tt>. Suppose further that 354 <tt class="literal">Ta</tt> has a cursor that reads <tt class="literal">record R</tt>, but does not modify it. Normally, 355 <tt class="literal">Tb</tt> would then be unable to write <tt class="literal">record R</tt> because 356 <tt class="literal">Ta</tt> would be holding a read lock on it. But when you configure your transaction for 357 committed reads, <tt class="literal">Tb</tt> <span class="emphasis"><em>can</em></span> modify <tt class="literal">record 358 R</tt> before <tt class="literal">Ta</tt> completes, so long as the reading cursor is no longer 359 addressing the 360 361 <span> 362 record or page. 363 </span> 364 365 </p> 366 <p> 367 When you configure your application for this level of isolation, you may see better performance 368 throughput because there are fewer read locks being held by your transactions. 369 Read committed isolation is most useful when you have a cursor that is reading and/or writing records in 370 a single direction, and that does not ever have to go back to re-read those same records. In this case, 371 you can allow DB to release read locks as it goes, rather than hold them for the life of the 372 transaction. 373 </p> 374 <p> 375 To configure your application to use committed reads, do one of the following: 376 </p> 377 <div class="itemizedlist"> 378 <ul type="disc"> 379 <li> 380 <p> 381 Create your transaction such that it allows committed reads. You do this by 382 <span> 383 specifying <tt class="literal">DB_READ_COMMITTED</tt> when you open the transaction. 384 </span> 385 386 </p> 387 </li> 388 <li> 389 <p> 390 <span> 391 Specify <tt class="literal">DB_READ_COMMITTED</tt> 392 when you open the cursor. 393 </span> 394 395 </p> 396 </li> 397 </ul> 398 </div> 399 <p> 400 For example, the following creates a transaction that allows committed reads: 401 </p> 402 <pre class="programlisting">#include <stdio.h> 403#include <stdlib.h> 404 405#include "db.h" 406 407int 408main(void) 409{ 410 int ret, ret_c; 411 u_int32_t db_flags, env_flags; 412 DB *dbp; 413 DB_ENV *envp; 414 DB_TXN *txn; 415 const char *db_home_dir = "/tmp/myEnvironment"; 416 const char *file_name = "mydb.db"; 417 418 dbp = NULL; 419 envp = NULL; 420 421 /* Open the environment */ 422 ret = db_env_create(&envp, 0); 423 if (ret != 0) { 424 fprintf(stderr, "Error creating environment handle: %s\n", 425 db_strerror(ret)); 426 return (EXIT_FAILURE); 427 } 428 429 env_flags = DB_CREATE | /* If the environment does not 430 * exist, create it. */ 431 DB_INIT_LOCK | /* Initialize locking */ 432 DB_INIT_LOG | /* Initialize logging */ 433 DB_INIT_MPOOL | /* Initialize the cache */ 434 DB_THREAD | /* Free-thread the env handle. */ 435 DB_INIT_TXN; /* Initialize transactions */ 436 437 ret = envp->open(envp, db_home_dir, env_flags, 0); 438 if (ret != 0) { 439 fprintf(stderr, "Error opening environment: %s\n", 440 db_strerror(ret)); 441 goto err; 442 } 443 444 /* Initialize the DB handle */ 445 ret = db_create(&dbp, envp, 0); 446 if (ret != 0) { 447 envp->err(envp, ret, "Database creation failed"); 448 goto err; 449 } 450 451 /* 452 * Notice that we do not have to specify any flags to the database to 453 * allow committed reads (this is as opposed to uncommitted reads 454 * where we DO have to specify a flag on the database open. 455 */ 456 db_flags = DB_CREATE | DB_AUTO_COMMIT; 457 ret = dbp->open(dbp, /* Pointer to the database */ 458 NULL, /* Txn pointer */ 459 file_name, /* File name */ 460 NULL, /* Logical db name */ 461 DB_BTREE, /* Database type (using btree) */ 462 db_flags, /* Open flags */ 463 0); /* File mode. Using defaults */ 464 if (ret != 0) { 465 envp->err(envp, ret, "Database '%s' open failed", 466 file_name); 467 goto err; 468 } 469 470 /* Get the txn handle */ 471 txn = NULL; 472 /* 473 * Open the transaction and enable committed reads. All cursors open 474 * with this transaction handle will use read committed isolation. 475 */ 476 ret = envp->txn_begin(envp, NULL, &txn, DB_READ_COMMITTED); 477 if (ret != 0) { 478 envp->err(envp, ret, "Transaction begin failed."); 479 goto err; 480 } 481 482 /* 483 * From here, you perform your database reads and writes as normal, 484 * committing and aborting the transactions as is necessary, and 485 * testing for deadlock exceptions as normal (omitted for brevity). 486 * 487 * Using transactional cursors with concurrent applications is 488 * described in more detail in the following section. 489 */ 490 491 ... </pre> 492 </div> 493 <div class="sect2" lang="en" xml:lang="en"> 494 <div class="titlepage"> 495 <div> 496 <div> 497 <h3 class="title"><a id="snapshot_isolation"></a>Using Snapshot Isolation</h3> 498 </div> 499 </div> 500 <div></div> 501 </div> 502 <p> 503 By default DB uses serializable isolation. An 504 important side effect of this isolation level is that 505 read operations obtain read locks on database pages, 506 and then hold those locks until the read operation is 507 completed. 508 509 <span> 510 When you are using transactional cursors, this 511 means that read locks are held until the transaction commits or 512 aborts. In that case, over time a transactional cursor 513 can gradually block all other transactions from writing 514 to the database. 515 </span> 516 </p> 517 <p> 518 You can avoid this by using snapshot isolation. 519 Snapshot isolation uses <span class="emphasis"><em>multiversion 520 concurrency control</em></span> to guarantee 521 repeatable reads. What this means is that every time a 522 writer would take a read lock on a page, instead a copy of 523 the page is made and the writer operates on that page 524 copy. This frees other writers from blocking due to a 525 read lock held on the page. 526 </p> 527 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 528 <h3 class="title">Note</h3> 529 <p> 530 Snapshot isolation is strongly recommended for read-only threads when writer 531 threads are also running, as this will eliminate read-write contention and 532 greatly improve transaction throughput for your writer threads. However, in 533 order for snapshot isolation to work for your reader-only threads, you must 534 of course use transactions for your DB reads. 535 </p> 536 </div> 537 <div class="sect3" lang="en" xml:lang="en"> 538 <div class="titlepage"> 539 <div> 540 <div> 541 <h4 class="title"><a id="sisolation_cost"></a>Snapshot Isolation Cost</h4> 542 </div> 543 </div> 544 <div></div> 545 </div> 546 <p> 547 Snapshot isolation does not come without a cost. 548 Because pages are being duplicated before being 549 operated upon, the cache will fill up faster. This 550 means that you might need a larger cache in order to 551 hold the entire working set in memory. 552 </p> 553 <p> 554 If the cache becomes full of page copies before old 555 copies can be discarded, additional I/O will occur as 556 pages are written to temporary "freezer" files on disk. 557 This can substantially reduce throughput, and should be 558 avoided if possible by configuring a large cache and 559 keeping snapshot isolation transactions short. 560 </p> 561 <p> 562 You can estimate how large your cache should be by 563 taking a checkpoint, followed by a call to the 564 <tt class="methodname">DB_ENV->log_archive()</tt> 565 566 567 method. The amount of cache required is approximately 568 double the size of the remaining log files (that is, 569 the log files that cannot be archived). 570 </p> 571 </div> 572 <div class="sect3" lang="en" xml:lang="en"> 573 <div class="titlepage"> 574 <div> 575 <div> 576 <h4 class="title"><a id="sisolation_maxtxn"></a>Snapshot Isolation Transactional Requirements</h4> 577 </div> 578 </div> 579 <div></div> 580 </div> 581 <p> 582 In addition to an increased cache size, you may also 583 need to increase the maximum number of transactions 584 that your application supports. (See 585 <a href="maxtxns.html">Configuring the Transaction Subsystem</a> 586 for details on how to set this.) 587 In the worst case scenario, you might need to configure your application for one 588 more transaction for every page in the cache. This is 589 because transactions are retained until the last page 590 they created is evicted from the cache. 591 </p> 592 </div> 593 <div class="sect3" lang="en" xml:lang="en"> 594 <div class="titlepage"> 595 <div> 596 <div> 597 <h4 class="title"><a id="sisolation_whenuse"></a>When to Use Snapshot Isolation</h4> 598 </div> 599 </div> 600 <div></div> 601 </div> 602 <p> 603 Snapshot isolation is best used when all or most 604 of the following conditions are true: 605 </p> 606 <div class="itemizedlist"> 607 <ul type="disc"> 608 <li> 609 <p> 610 You can have a large cache relative to your working data set size. 611 </p> 612 </li> 613 <li> 614 <p> 615 You require repeatable reads. 616 </p> 617 </li> 618 <li> 619 <p> 620 You will be using transactions that routinely work on 621 the entire database, or more commonly, 622 there is data in your database that will be very 623 frequently written by more than one transaction. 624 </p> 625 </li> 626 <li> 627 <p> 628 Read/write contention is 629 limiting your application's 630 throughput, or the application 631 is all or mostly read-only and 632 contention for the lock manager 633 mutex is limiting throughput. 634 </p> 635 </li> 636 </ul> 637 </div> 638 </div> 639 <div class="sect3" lang="en" xml:lang="en"> 640 <div class="titlepage"> 641 <div> 642 <div> 643 <h4 class="title"><a id="sisolation_howuse"></a>How to use Snapshot Isolation</h4> 644 </div> 645 </div> 646 <div></div> 647 </div> 648 <p> 649 You use snapshot isolation by: 650 </p> 651 <div class="itemizedlist"> 652 <ul type="disc"> 653 <li> 654 <p> 655 Opening the database with 656 multiversion support. You can 657 configure this either when you 658 open your environment or when 659 you open your 660 661 <span> 662 database. 663 </span> 664 665 666 <span> 667 Use the 668 <tt class="literal">DB_MULTIVERSION</tt> 669 flag to configure this support. 670 </span> 671 672 673 </p> 674 </li> 675 <li> 676 <p> 677 Configure your <span>cursor or</span> 678 transaction to use snapshot isolation. 679 </p> 680 <p> 681 To do this, 682 683 <span> 684 pass the <tt class="literal">DB_TXN_SNAPSHOT</tt> flag 685 when you 686 687 <span> 688 open the cursor or 689 </span> 690 691 create the transaction. 692 693 <span> 694 If configured for the transaction, 695 then this flag is not required 696 when the cursor is opened. 697 </span> 698 699 </span> 700 701 702 </p> 703 </li> 704 </ul> 705 </div> 706 <p> 707 The simplest way to take advantage of snapshot 708 isolation is for queries: keep update 709 transactions using full read/write locking and 710 use snapshot isolation on read-only transactions or 711 cursors. This should minimize blocking of 712 snapshot isolation transactions and will avoid 713 deadlock errors. 714 </p> 715 <p> 716 If the application has update transactions which 717 read many items and only update a small set (for 718 example, scanning until a desired record is 719 found, then modifying it), throughput may be 720 improved by running some updates at snapshot 721 isolation as well. But doing this means that 722 you must manage deadlock errors. 723 See 724 <a href="lockingsubsystem.html#deadlockresolve">Resolving Deadlocks</a> 725 for details. 726 </p> 727 <p> 728 The following code fragment turns 729 on snapshot isolation for a transaction: 730 </p> 731 <pre class="programlisting">#include <stdio.h> 732#include <stdlib.h> 733 734#include "db.h" 735 736int 737main(void) 738{ 739 int ret, ret_c; 740 u_int32_t db_flags, env_flags; 741 DB *dbp; 742 DB_ENV *envp; 743 const char *db_home_dir = "/tmp/myEnvironment"; 744 const char *file_name = "mydb.db"; 745 746 dbp = NULL; 747 envp = NULL; 748 749 /* Open the environment */ 750 ret = db_env_create(&envp, 0); 751 if (ret != 0) { 752 fprintf(stderr, "Error creating environment handle: %s\n", 753 db_strerror(ret)); 754 return (EXIT_FAILURE); 755 } 756 757 env_flags = DB_CREATE | /* Create the environment if it does 758 * not already exist. */ 759 DB_INIT_TXN | /* Initialize transactions */ 760 DB_INIT_LOCK | /* Initialize locking. */ 761 DB_INIT_LOG | /* Initialize logging */ 762 DB_INIT_MPOOL| /* Initialize the in-memory cache. */ 763 <b class="userinput"><tt>DB_MULTIVERSION; /* Support snapshot isolation */</tt></b> 764 765 ret = envp->open(envp, db_home_dir, env_flags, 0); 766 if (ret != 0) { 767 fprintf(stderr, "Error opening environment: %s\n", 768 db_strerror(ret)); 769 goto err; 770 } 771 772 /* Initialize the DB handle */ 773 ret = db_create(&dbp, envp, 0); 774 if (ret != 0) { 775 envp->err(envp, ret, "Database creation failed"); 776 goto err; 777 } 778 779 /* 780 * Nothing needs to be supplied here to support snapshot isolation. 781 * The environment does, so its databases will too. 782 */ 783 db_flags = DB_CREATE | DB_AUTO_COMMIT; 784 ret = dbp->open(dbp, /* Pointer to the database */ 785 NULL, /* Txn pointer */ 786 file_name, /* File name */ 787 NULL, /* Logical db name */ 788 DB_BTREE, /* Database type (using btree) */ 789 db_flags, /* Open flags */ 790 0); /* File mode. Using defaults */ 791 if (ret != 0) { 792 envp->err(envp, ret, "Database '%s' open failed", 793 file_name); 794 goto err; 795 } 796 797 798 .... 799 800 ret = envp->txn_begin(envp, NULL, &txn, <b class="userinput"><tt>DB_TXN_SNAPSHOT</tt></b>); 801 802 /* remainder of the program omitted for brevity */ 803 804 </pre> 805 </div> 806 </div> 807 </div> 808 <div class="navfooter"> 809 <hr /> 810 <table width="100%" summary="Navigation footer"> 811 <tr> 812 <td width="40%" align="left"><a accesskey="p" href="lockingsubsystem.html">Prev</a> </td> 813 <td width="20%" align="center"> 814 <a accesskey="u" href="txnconcurrency.html">Up</a> 815 </td> 816 <td width="40%" align="right"> <a accesskey="n" href="txn_ccursor.html">Next</a></td> 817 </tr> 818 <tr> 819 <td width="40%" align="left" valign="top">The Locking Subsystem </td> 820 <td width="20%" align="center"> 821 <a accesskey="h" href="index.html">Home</a> 822 </td> 823 <td width="40%" align="right" valign="top"> Transactional Cursors and Concurrent Applications</td> 824 </tr> 825 </table> 826 </div> 827 </body> 828</html> 829