txn_ccursor.html   [plain text]


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Transactional Cursors and Concurrent Applications</title>
    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
    <link rel="home" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
    <link rel="up" href="txnconcurrency.html" title="Chapter 4. Concurrency" />
    <link rel="previous" href="isolation.html" title="Isolation" />
    <link rel="next" href="readmodifywrite.html" title="Read/Modify/Write" />
  </head>
  <body>
    <div class="navheader">
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Transactional Cursors and Concurrent Applications</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="isolation.html">Prev</a> </td>
          <th width="60%" align="center">Chapter 4. Concurrency</th>
          <td width="20%" align="right"> <a accesskey="n" href="readmodifywrite.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" lang="en" xml:lang="en">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="txn_ccursor"></a>Transactional Cursors and Concurrent Applications</h2>
          </div>
        </div>
        <div></div>
      </div>
      <p>
            When you use transactional cursors with a concurrent application, remember that 
            in the event of a deadlock you must make sure that you close your cursor before you abort and retry your
            transaction. 
         </p>
      <p>
            Also, remember that when you are using the default isolation level, 
            every time your cursor reads a record it locks
            that record until the encompassing transaction is resolved. This
            means that walking your database with a transactional cursor
            increases the chance of lock contention. 
          </p>
      <p>
                For this reason, if you must routinely walk your database with a
                transactional cursor, consider using a reduced isolation level
                such as read committed. 
          </p>
      <div class="sect2" lang="en" xml:lang="en">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="cursordirtyreads"></a>Using Cursors with Uncommitted Data</h3>
            </div>
          </div>
          <div></div>
        </div>
        <p>

                As described in <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a> 
                above, it is possible to relax your transaction's isolation
                level such that it can read data modified but not yet committed
                by another transaction. You can configure this when you create
                your transaction handle, and when you do so then all cursors opened
                inside that transaction will automatically use uncommitted reads. 
            </p>
        <p>
                You can also do this when you create a cursor handle from within 
                a serializable transaction.  When you do this, only those 
                cursors configured for uncommitted reads uses uncommitted reads.
            </p>
        <p>
                    Either way, you must first configure your database
                     handle to support
                uncommitted reads before you can configure your transactions or
                your cursors to use them.
            </p>
        <p>
                The following example shows how to configure an individual cursor handle 
                to read uncommitted data from within a serializable (full isolation) transaction. 
                For an example of
                configuring a transaction to perform uncommitted reads in
                general, see <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a>.
            </p>
        <pre class="programlisting">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include "db.h"

int
main(void)
{
    DB *dbp;
    DBC *cursorp;
    DB_ENV *envp;
    DB_TXN *txn;
    int ret, c_ret;
    char *replacementString = "new string";

    dbp = NULL;
    envp = NULL;
    txn = NULL;

    /* Open the environment */
    ret = db_env_create(&amp;envp, 0);
    if (ret != 0) {
        fprintf(stderr, "Error creating environment handle: %s\n",
            db_strerror(ret));
        return (EXIT_FAILURE);
    }
                                                                                                                                  
    env_flags = DB_CREATE |    /* Create the environment if it does 
                                * not already exist. */
                DB_INIT_TXN  | /* Initialize transactions */
                DB_INIT_LOCK | /* Initialize locking. */
                DB_INIT_LOG  | /* Initialize logging */
                DB_INIT_MPOOL; /* Initialize the in-memory cache. */

    ret = envp-&gt;open(envp, db_home_dir, env_flags, 0);
    if (ret != 0) {
        fprintf(stderr, "Error opening environment: %s\n",
            db_strerror(ret));
        goto err;
    }

    /* Initialize the DB handle */
    ret = db_create(&amp;dbp, envp, 0);
    if (ret != 0) {
        envp-&gt;err(envp, ret, "Database creation failed");
        goto err;
    }

    db_flags = DB_CREATE |             /* Create the db if it does not 
                                        * exist */
               DB_AUTO_COMMIT |        /* Enable auto commit */
               DB_READ_UNCOMMITTED;    /* Enable uncommitted reads */

    ret = dbp-&gt;open(dbp,        /* Pointer to the database */
                    NULL,       /* Txn pointer */
                    file_name,  /* File name */
                    NULL,       /* Logical db name */
                    DB_BTREE,   /* Database type (using btree) */
                    db_flags,   /* Open flags */
                    0);         /* File mode. Using defaults */
    if (ret != 0) {
        envp-&gt;err(envp, ret, "Database '%s' open failed",
            file_name);
        goto err;
    }

    /* Get the txn handle */
    /* Note that this is a degree 3 transaction */
    ret = envp-&gt;txn_begin(envp, NULL, &amp;txn, 0);
    if (ret != 0) {
        envp-&gt;err(envp, ret, "Transaction begin failed.");
        goto err;
    }

    /* Get the cursor, supply the txn handle at that time */
    /* Cause the cursor to perform uncommitted reads */
    ret = dbp-&gt;cursor(dbp, txn, &amp;cursorp, DB_READ_UNCOMMITTED);
    if (ret != 0) {
        envp-&gt;err(envp, ret, "Cursor open failed.");
        txn-&gt;abort(txn);
        goto err;
    }

    /*
     * From here, you perform your cursor reads and writes as normal,
     * committing and aborting the transactions as is necessary, and 
     * testing for deadlock exceptions as normal (omitted for brevity). 
     */

     ...  </pre>
      </div>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="isolation.html">Prev</a> </td>
          <td width="20%" align="center">
            <a accesskey="u" href="txnconcurrency.html">Up</a>
          </td>
          <td width="40%" align="right"> <a accesskey="n" href="readmodifywrite.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Isolation </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Read/Modify/Write</td>
        </tr>
      </table>
    </div>
  </body>
</html>