diff options
Diffstat (limited to 'bdb/docs/ref/transapp/inc.html')
-rw-r--r-- | bdb/docs/ref/transapp/inc.html | 201 |
1 files changed, 0 insertions, 201 deletions
diff --git a/bdb/docs/ref/transapp/inc.html b/bdb/docs/ref/transapp/inc.html deleted file mode 100644 index 35cf67d7efa..00000000000 --- a/bdb/docs/ref/transapp/inc.html +++ /dev/null @@ -1,201 +0,0 @@ -<!--$Id: inc.so,v 1.6 2000/08/08 19:58:20 bostic Exp $--> -<!--Copyright 1997, 1998, 1999, 2000 by Sleepycat Software, Inc.--> -<!--All rights reserved.--> -<html> -<head> -<title>Berkeley DB Reference Guide: Atomicity</title> -<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit."> -<meta name="keywords" content="embedded,database,programmatic,toolkit,b+tree,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,java,C,C++"> -</head> -<body bgcolor=white> -<table><tr valign=top> -<td><h3><dl><dt>Berkeley DB Reference Guide:<dd>Transaction Protected Applications</dl></h3></td> -<td width="1%"><a href="../../ref/transapp/put.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../ref/toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/transapp/read.html"><img src="../../images/next.gif" alt="Next"></a> -</td></tr></table> -<p> -<h1 align=center>Atomicity</h1> -<p>The third reason listed for using transactions was atomicity. Consider -an application suite where multiple threads of control (multiple -processes or threads in one or more processes) are changing the values -associated with a key in one or more databases. Specifically, they are -taking the current value, incrementing it, and then storing it back into -the database. -<p>Such an application requires atomicity. Since we want to change a value -in the database, we must make sure that once we read it, no other thread -of control modifies it. For example, assume that both thread #1 and -thread #2 are doing similar operations in the database, where thread #1 -is incrementing records by 3, and thread #2 is incrementing records by -5. We want to increment the record by a total of 8. If the operations -interleave in the right (well, wrong) order, that is not what will -happen: -<p><blockquote><pre>thread #1 <b>read</b> record: the value is 2 -thread #2 <b>read</b> record: the value is 2 -thread #2 <b>write</b> record + 5 back into the database (new value 7) -thread #1 <b>write</b> record + 3 back into the database (new value 5)</pre></blockquote> -<p>As you can see, instead of incrementing the record by a total of 8, -we've only incremented it by 3, because thread #1 overwrote thread #2's -change. By wrapping the operations in transactions, we ensure that this -cannot happen. In a transaction, when the first thread reads the -record, locks are acquired that will not be released until the -transaction finishes, guaranteeing that all other readers and writers -will block, waiting for the first thread's transaction to complete (or -to be aborted). -<p>Here is an example function that does transaction-protected increments -on database records to ensure atomicity. -<p><blockquote><pre>int -main(int argc, char *argv) -{ - extern char *optarg; - extern int optind; - DB *db_cats, *db_color, *db_fruit; - DB_ENV *dbenv; - pthread_t ptid; - int ch; -<p> - while ((ch = getopt(argc, argv, "")) != EOF) - switch (ch) { - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; -<p> - env_dir_create(); - env_open(&dbenv); -<p> - /* Open database: Key is fruit class; Data is specific type. */ - db_open(dbenv, &db_fruit, "fruit", 0); -<p> - /* Open database: Key is a color; Data is an integer. */ - db_open(dbenv, &db_color, "color", 0); -<p> - /* - * Open database: - * Key is a name; Data is: company name, address, cat breeds. - */ - db_open(dbenv, &db_cats, "cats", 1); -<p> - add_fruit(dbenv, db_fruit, "apple", "yellow delicious"); -<p> -<b> add_color(dbenv, db_color, "blue", 0); - add_color(dbenv, db_color, "blue", 3);</b> -<p> - return (0); -} -<p> -<b>void -add_color(DB_ENV *dbenv, DB *dbp, char *color, int increment) -{ - DBT key, data; - DB_TXN *tid; - int original, ret; - char buf64; -<p> - /* Initialization. */ - memset(&key, 0, sizeof(key)); - key.data = color; - key.size = strlen(color); - memset(&data, 0, sizeof(data)); - data.flags = DB_DBT_MALLOC; -<p> - for (;;) { - /* Begin the transaction. */ - if ((ret = txn_begin(dbenv, NULL, &tid, 0)) != 0) { - dbenv->err(dbenv, ret, "txn_begin"); - exit (1); - } -<p> - /* - * Get the key. If it exists, we increment the value. If it - * doesn't exist, we create it. - */ - switch (ret = dbp->get(dbp, tid, &key, &data, 0)) { - case 0: - original = atoi(data.data); - break; - case DB_LOCK_DEADLOCK: - /* Deadlock: retry the operation. */ - if ((ret = txn_abort(tid)) != 0) { - dbenv->err(dbenv, ret, "txn_abort"); - exit (1); - } - continue; - case DB_NOTFOUND: - original = 0; - break; - default: - /* Error: run recovery. */ - dbenv->err( - dbenv, ret, "dbc->get: %s/%d", color, increment); - exit (1); - } - if (data.data != NULL) - free(data.data); -<p> - /* Create the new data item. */ - (void)snprintf(buf, sizeof(buf), "%d", original + increment); - data.data = buf; - data.size = strlen(buf) + 1; -<p> - /* Store the new value. */ - switch (ret = dbp->put(dbp, tid, &key, &data, 0)) { - case 0: - /* Success: commit the change. */ - if ((ret = txn_commit(tid, 0)) != 0) { - dbenv->err(dbenv, ret, "txn_commit"); - exit (1); - } - return; - case DB_LOCK_DEADLOCK: - /* Deadlock: retry the operation. */ - if ((ret = txn_abort(tid)) != 0) { - dbenv->err(dbenv, ret, "txn_abort"); - exit (1); - } - break; - default: - /* Error: run recovery. */ - dbenv->err( - dbenv, ret, "dbc->put: %s/%d", color, increment); - exit (1); - } - } -}</b></pre></blockquote> -<p>Any number of operations, on any number of databases, can be included -in a single transaction to ensure atomicity of the operations. There -is, however, a trade-off between the number of operations included in -a single transaction and both throughput and the possibility of -deadlock. The reason for this is because transactions acquire locks -throughout their lifetime, and do not release them until transaction -commit or abort. So, the more operations included in a transaction, -the more likely that a transaction will block other operations and that -deadlock will occur. However, each transaction commit requires a -synchronous disk I/O, so grouping multiple operations into a transaction -can increase overall throughput. (There is one exception to this. The -<a href="../../api_c/env_open.html#DB_TXN_NOSYNC">DB_TXN_NOSYNC</a> option causes transactions to exhibit the ACI -(atomicity, consistency and isolation) properties, but not D -(durability), avoiding the synchronous disk I/O on transaction commit -and greatly increasing transaction throughput for some applications. -<p>When applications do create complex transactions, they often avoid -having more than one complex transaction at a time, as simple operations -like a single <a href="../../api_c/db_put.html">DB->put</a> are unlikely to deadlock with each other -or the complex transaction, while multiple complex transactions are -likely to deadlock with each other as they will both acquire many locks -over their lifetime. Alternatively, complex transactions can be broken -up into smaller sets of operations, and each of those sets may be -encapsulated in a nested transaction. Because nested transactions may -be individually aborted and retried without causing the entire -transaction to be aborted, this allows complex transactions to proceed -even in the face of heavy contention, repeatedly trying the -sub-operations until they succeed. -<p>It is also helpful to order operations within a transaction, that is, -access the databases and items within the databases in the same order, -to the extent possible, in all transactions. Accessing databases and -items in different orders greatly increases the likelihood of operations -being blocked and failing due to deadlocks. -<table><tr><td><br></td><td width="1%"><a href="../../ref/transapp/put.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../ref/toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/transapp/read.html"><img src="../../images/next.gif" alt="Next"></a> -</td></tr></table> -<p><font size=1><a href="http://www.sleepycat.com">Copyright Sleepycat Software</a></font> -</body> -</html> |