• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/db-4.8.30/docs/programmer_reference/
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.73.2" />
9    <link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
10    <link rel="up" href="transapp.html" title="Chapter��11.�� Berkeley DB Transactional Data Store Applications" />
11    <link rel="prev" href="transapp_atomicity.html" title="Atomicity" />
12    <link rel="next" href="transapp_read.html" title="Degrees of isolation" />
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="transapp_atomicity.html">Prev</a>��</td>
22          <th width="60%" align="center">Chapter��11.��
23		Berkeley DB Transactional Data Store Applications
24        </th>
25          <td width="20%" align="right">��<a accesskey="n" href="transapp_read.html">Next</a></td>
26        </tr>
27      </table>
28      <hr />
29    </div>
30    <div class="sect1" lang="en" xml:lang="en">
31      <div class="titlepage">
32        <div>
33          <div>
34            <h2 class="title" style="clear: both"><a id="transapp_inc"></a>Isolation</h2>
35          </div>
36        </div>
37      </div>
38      <p>The third reason listed for using transactions was <span class="emphasis"><em>isolation</em></span>.
39Consider an application suite in which multiple threads of control
40(multiple processes or threads in one or more processes) are changing
41the values associated with a key in one or more databases.  Specifically,
42they are taking the current value, incrementing it, and then storing it
43back into the database.</p>
44      <p>Such an application requires isolation.  Because we want to change a value
45in the database, we must make sure that after we read it, no other thread
46of control modifies it.  For example, assume that both thread #1 and
47thread #2 are doing similar operations in the database, where thread #1
48is incrementing records by 3, and thread #2 is incrementing records by
495.  We want to increment the record by a total of 8.  If the operations
50interleave in the right (well, wrong) order, that is not what will
51happen:</p>
52      <pre class="programlisting">thread #1  <span class="bold"><strong>read</strong></span> record: the value is 2
53thread #2  <span class="bold"><strong>read</strong></span> record: the value is 2
54thread #2  <span class="bold"><strong>write</strong></span> record + 5 back into the database (new value 7)
55thread #1  <span class="bold"><strong>write</strong></span> record + 3 back into the database (new value 5)</pre>
56      <p>As you can see, instead of incrementing the record by a total of 8,
57we've incremented it only by 3 because thread #1 overwrote thread #2's
58change.  By wrapping the operations in transactions, we ensure that this
59cannot happen.  In a transaction, when the first thread reads the
60record, locks are acquired that will not be released until the
61transaction finishes, guaranteeing that all writers
62will block, waiting for the first thread's transaction to complete (or
63to be aborted).</p>
64      <p>Here is an example function that does transaction-protected increments
65on database records to ensure isolation:</p>
66      <pre class="programlisting">int
67main(int argc, char *argv)
68{
69	extern int optind;
70	DB *db_cats, *db_color, *db_fruit;
71	DB_ENV *dbenv;
72	int ch;
73
74	while ((ch = getopt(argc, argv, "")) != EOF)
75		switch (ch) {
76		case '?':
77		default:
78			usage();
79		}
80	argc -= optind;
81	argv += optind;
82
83	env_dir_create();
84	env_open(&amp;dbenv);
85
86	/* Open database: Key is fruit class; Data is specific type. */
87	db_open(dbenv, &amp;db_fruit, "fruit", 0);
88
89	/* Open database: Key is a color; Data is an integer. */
90	db_open(dbenv, &amp;db_color, "color", 0);
91
92	/*
93	 * Open database:
94	 *	Key is a name; Data is: company name, cat breeds.
95	 */
96	db_open(dbenv, &amp;db_cats, "cats", 1);
97
98	add_fruit(dbenv, db_fruit, "apple", "yellow delicious");
99
100<span class="bold"><strong>	add_color(dbenv, db_color, "blue", 0);
101	add_color(dbenv, db_color, "blue", 3);</strong></span>
102
103	return (0);
104}
105
106<span class="bold"><strong>int
107add_color(DB_ENV *dbenv, DB *dbp, char *color, int increment)
108{
109	DBT key, data;
110	DB_TXN *tid;
111	int fail, original, ret, t_ret;
112	char buf64;
113
114	/* Initialization. */
115	memset(&amp;key, 0, sizeof(key));
116	key.data = color;
117	key.size = strlen(color);
118	memset(&amp;data, 0, sizeof(data));
119	data.flags = DB_DBT_MALLOC;
120
121	for (fail = 0;;) {
122		/* Begin the transaction. */
123		if ((ret = dbenv-&gt;txn_begin(dbenv, NULL, &amp;tid, 0)) != 0) {
124			dbenv-&gt;err(dbenv, ret, "DB_ENV-&gt;txn_begin");
125			exit (1);
126		}
127
128		/*
129		 * Get the key.  If it exists, we increment the value.  If it
130		 * doesn't exist, we create it.
131		 */
132		switch (ret = dbp-&gt;get(dbp, tid, &amp;key, &amp;data, DB_RMW)) {
133		case 0:
134			original = atoi(data.data);
135			break;
136		case DB_LOCK_DEADLOCK:
137		default:
138			/* Retry the operation. */
139			if ((t_ret = tid-&gt;abort(tid)) != 0) {
140				dbenv-&gt;err(dbenv, t_ret, "DB_TXN-&gt;abort");
141				exit (1);
142			}
143			if (fail++ == MAXIMUM_RETRY)
144				return (ret);
145			continue;
146		case DB_NOTFOUND:
147			original = 0;
148			break;
149		}
150		if (data.data != NULL)
151			free(data.data);
152
153		/* Create the new data item. */
154		(void)snprintf(buf, sizeof(buf), "%d", original + increment);
155		data.data = buf;
156		data.size = strlen(buf) + 1;
157
158		/* Store the new value. */
159		switch (ret = dbp-&gt;put(dbp, tid, &amp;key, &amp;data, 0)) {
160		case 0:
161			/* Success: commit the change. */
162			if ((ret = tid-&gt;commit(tid, 0)) != 0) {
163				dbenv-&gt;err(dbenv, ret, "DB_TXN-&gt;commit");
164				exit (1);
165			}
166			return (0);
167		case DB_LOCK_DEADLOCK:
168		default:
169			/* Retry the operation. */
170			if ((t_ret = tid-&gt;abort(tid)) != 0) {
171				dbenv-&gt;err(dbenv, t_ret, "DB_TXN-&gt;abort");
172				exit (1);
173			}
174			if (fail++ == MAXIMUM_RETRY)
175				return (ret);
176			break;
177		}
178	}
179}</strong></span></pre>
180      <p>The <a href="../api_reference/C/dbcget.html#dbcget_DB_RMW" class="olink">DB_RMW</a> flag in the <a href="../api_reference/C/dbget.html" class="olink">DB-&gt;get()</a> call specifies a write lock
181should be acquired on the key/data pair, instead of the more obvious read
182lock.  We do this because the application expects to write the key/data
183pair in a subsequent operation, and the transaction is much more likely to
184deadlock if we first obtain a read lock and subsequently a write lock, than
185if we obtain the write lock initially.</p>
186    </div>
187    <div class="navfooter">
188      <hr />
189      <table width="100%" summary="Navigation footer">
190        <tr>
191          <td width="40%" align="left"><a accesskey="p" href="transapp_atomicity.html">Prev</a>��</td>
192          <td width="20%" align="center">
193            <a accesskey="u" href="transapp.html">Up</a>
194          </td>
195          <td width="40%" align="right">��<a accesskey="n" href="transapp_read.html">Next</a></td>
196        </tr>
197        <tr>
198          <td width="40%" align="left" valign="top">Atomicity��</td>
199          <td width="20%" align="center">
200            <a accesskey="h" href="index.html">Home</a>
201          </td>
202          <td width="40%" align="right" valign="top">��Degrees of isolation</td>
203        </tr>
204      </table>
205    </div>
206  </body>
207</html>
208