Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
BIN
docs/gsg_txn/JAVA/BerkeleyDB-Core-JAVA-Txn.pdf
Normal file
BIN
docs/gsg_txn/JAVA/BerkeleyDB-Core-JAVA-Txn.pdf
Normal file
Binary file not shown.
99
docs/gsg_txn/JAVA/abortresults.html
Normal file
99
docs/gsg_txn/JAVA/abortresults.html
Normal file
@@ -0,0 +1,99 @@
|
||||
<?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>Aborting a Transaction</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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="next" href="autocommit.html" title="Auto Commit" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Aborting a Transaction</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="usingtxns.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="autocommit.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="abortresults"></a>Aborting a Transaction</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When you abort a transaction, all database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
modifications performed
|
||||
under the protection of the transaction are discarded, and all
|
||||
locks currently held by the transaction are released. In this event,
|
||||
your data is simply left in the
|
||||
state that it was in before the transaction began performing data
|
||||
modifications.
|
||||
</p>
|
||||
<p>
|
||||
Note that aborting a transaction may result in disk
|
||||
<span>
|
||||
I/O if your logs are backed by the filesystem.
|
||||
</span>
|
||||
|
||||
It is possible that during the course of your transaction,
|
||||
logging data and/or database
|
||||
<span>pages</span>
|
||||
|
||||
were written to backing files on disk. For this reason, DB
|
||||
notes that the abort occurred in its log files so that at a
|
||||
minimum the database can be brought into a consistent state at
|
||||
recovery time.
|
||||
</p>
|
||||
<p>
|
||||
Also, once you have aborted a transaction, the transaction
|
||||
handle that you used for the transaction is no longer valid. To
|
||||
perform database activities under the control of a new
|
||||
transaction, you must obtain a fresh transactional handle.
|
||||
</p>
|
||||
<p>
|
||||
To abort a transaction, call
|
||||
|
||||
|
||||
<span><tt class="methodname">Transaction.abort()</tt>.</span>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="usingtxns.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="autocommit.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 3. Transaction Basics </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Auto Commit</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
337
docs/gsg_txn/JAVA/architectrecovery.html
Normal file
337
docs/gsg_txn/JAVA/architectrecovery.html
Normal file
@@ -0,0 +1,337 @@
|
||||
<?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>Designing Your Application for Recovery</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="recovery.html" title="Recovery Procedures" />
|
||||
<link rel="next" href="hotfailover.html" title="Using Hot Failovers" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Designing Your Application for Recovery</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="recovery.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="hotfailover.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="architectrecovery"></a>Designing Your Application for Recovery</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When building your DB application, you should consider how you will run recovery. If you are building a
|
||||
single threaded, single process application, it is fairly simple to run recovery when your application first
|
||||
opens its environment. In this case, you need only decide if you want to run recovery every time you open
|
||||
your application (recommended) or only some of the time, presumably triggered by a start up option
|
||||
controlled by your application's user.
|
||||
</p>
|
||||
<p>
|
||||
However, for multi-threaded and multi-process applications, you need to carefully consider how you will
|
||||
design your application's startup code so as to run recovery only when it makes sense to do so.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="multithreadrecovery"></a>Recovery for Multi-Threaded Applications</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If your application uses only one environment handle, then handling recovery for a multi-threaded
|
||||
application is no more difficult than for a single threaded application. You simply open the environment
|
||||
in the application's main thread, and then pass that handle to each of the threads that will be
|
||||
performing DB operations. We illustrate this with our final example in this book (see
|
||||
|
||||
<a href="txnexample_java.html">Base API Transaction Example</a>
|
||||
|
||||
|
||||
for more information).
|
||||
</p>
|
||||
<p>
|
||||
Alternatively, you can have each worker thread open its own environment handle. However, in this case,
|
||||
designing for recovery is a bit more complicated.
|
||||
</p>
|
||||
<p>
|
||||
Generally, when a thread performing database operations fails
|
||||
or hangs, it is frequently best to simply
|
||||
restart the application and run recovery upon application
|
||||
startup as normal. However, not all applications can afford
|
||||
to restart because a single thread has misbehaved.
|
||||
</p>
|
||||
<p>
|
||||
If you are attempting to continue operations in the face of a misbehaving thread,
|
||||
then at a minimum recovery must be run if a thread performing database operations fails or hangs.
|
||||
</p>
|
||||
<p>
|
||||
Remember that recovery clears the environment of all
|
||||
outstanding locks, including any that might be outstanding
|
||||
from an aborted thread. If these locks are not cleared,
|
||||
other threads performing database operations can back up
|
||||
behind the locks obtained but never cleared by the failed
|
||||
thread. The result will be an application that hangs
|
||||
indefinitely.
|
||||
</p>
|
||||
<p>
|
||||
To run recovery under these circumstances:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Suspend or shutdown all other threads performing
|
||||
database operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Discarding any open environment handles. Note that
|
||||
attempting to gracefully close these handles may be
|
||||
asking for trouble; the close can fail if the
|
||||
environment is already in need of recovery. For
|
||||
this reason, it is best and easiest to simply discard the handle.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Open new handles, running recovery as you open
|
||||
them.
|
||||
See <a href="recovery.html#normalrecovery">Normal Recovery</a> for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Restart all your database threads.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
A traditional way to handle this activity is to spawn a watcher thread that is responsible for making
|
||||
sure all is well with your threads, and performing the above actions if not.
|
||||
</p>
|
||||
<p>
|
||||
However, in the case where each worker thread opens and maintains its own environment handle, recovery
|
||||
is complicated for two reasons:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
For some applications and workloads, it might be
|
||||
worthwhile to give your database threads the
|
||||
ability to gracefully finalize any on-going
|
||||
transactions. If this is the case, your
|
||||
code must be capable of signaling each thread
|
||||
to halt DB activities and close its
|
||||
environment. If you simply run recovery against the
|
||||
environment, your database threads will
|
||||
detect this and fail in the midst of performing their
|
||||
database operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Your code must be capable of ensuring only one
|
||||
thread runs recovery before allowing all other
|
||||
threads to open their respective environment
|
||||
handles. Recovery should be single threaded because when
|
||||
recovery is run against an environment, it is
|
||||
deleted and then recreated. This will cause all
|
||||
other processes and threads to "fail" when they
|
||||
attempt operations against the newly recovered
|
||||
environment. If all threads run recovery
|
||||
when they start up, then it is likely that some
|
||||
threads will fail because the environment that they
|
||||
are using has been recovered. This will cause the thread to have to re-execute its own recovery
|
||||
path. At best, this is inefficient and at worst it could cause your application to fall into an
|
||||
endless recovery pattern.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="multiprocessrecovery"></a>Recovery in Multi-Process Applications</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Frequently, DB applications use multiple processes to interact with the databases. For example, you may
|
||||
have a long-running process, such as some kind of server, and then a series of administrative tools that
|
||||
you use to inspect and administer the underlying databases. Or, in some web-based architectures, different
|
||||
services are run as independent processes that are managed by the server.
|
||||
</p>
|
||||
<p>
|
||||
In any case, recovery for a multi-process environment is complicated for two reasons:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
In the event that recovery must be run, you might
|
||||
want to notify processes interacting with the environment
|
||||
that recovery is about to occur and give them a
|
||||
chance to gracefully terminate. Whether it is
|
||||
worthwhile for you to do this is entirely dependent
|
||||
upon the nature of your application. Some
|
||||
long-running applications with multiple processes
|
||||
performing meaningful work might want to do this.
|
||||
Other applications with processes performing database
|
||||
operations that are likely to be harmed by error conditions in other
|
||||
processes will likely find it to be not worth the
|
||||
effort. For this latter group, the chances of
|
||||
performing a graceful shutdown may be low anyway.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Unlike single process scenarios, it can quickly become wasteful for every process interacting
|
||||
with the databases to run recovery when it starts up. This is partly because recovery
|
||||
<span class="emphasis"><em>does</em></span> take some amount of time to run, but mostly you want to
|
||||
avoid a situation where your server must
|
||||
reopen all its environment handles just because you fire up a command line database
|
||||
administrative utility that always runs recovery.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
The following sections describe a mechanism that you can use to determine if and when you should run
|
||||
recovery in a multi-process application.
|
||||
</p>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="mp_recover_effects"></a>Effects of Multi-Process Recovery</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before continuing, it is worth noting that the following sections describe recovery processes than
|
||||
can result in one process running recovery while other processes are currently actively performing
|
||||
database operations.
|
||||
</p>
|
||||
<p>
|
||||
When this happens, the current database operation will
|
||||
abnormally fail, indicating a DB_RUNRECOVERY condition.
|
||||
This means that your application should immediately abandon any database operations that it may have
|
||||
on-going, discard any environment handles it has opened, and obtain and open new handles.
|
||||
</p>
|
||||
<p>
|
||||
The net effect of this is that any writes performed by unresolved transactions will be lost.
|
||||
For persistent applications (servers, for example), the services it provides will also be
|
||||
unavailable for the amount of time that it takes to complete a recovery and for all participating
|
||||
processes to reopen their environment handles.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="db_register"></a>Process Registration</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
One way to handle multi-process recovery is for every process to "register" its environment. In
|
||||
doing so, the process gains the ability to see if any other applications are using the
|
||||
environment and, if so, whether they have suffered an abnormal termination. If an abnormal
|
||||
termination is detected, the process runs recovery; otherwise, it does not.
|
||||
</p>
|
||||
<p>
|
||||
Note that using process registration also ensures that
|
||||
recovery is serialized across applications. That is,
|
||||
only one process at a time has a chance to run
|
||||
recovery. Generally this means that the first process
|
||||
to start up will run recovery, and all other processes
|
||||
will silently not run recovery because it is not
|
||||
needed.
|
||||
</p>
|
||||
<p>
|
||||
To cause your application to register its environment, you specify
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the <tt class="methodname">EnvironmentConfig.setRegister()</tt>
|
||||
method when you open your environment. Note that you must also specify
|
||||
<tt class="literal">true</tt> to either <tt class="methodname">EnvironmentConfig.setRunRecovery()</tt>
|
||||
or <tt class="methodname">EnvironmentConfig.setRunFatalRecovery()</tt>.
|
||||
</span>
|
||||
If during the open, DB determines that recovery must be run, this indicates the type of
|
||||
recovery that is run. If you do not specify either type of recovery, then no recovery is run if
|
||||
the registration process identifies a need for it. In this case, the environment open simply
|
||||
fails by
|
||||
|
||||
<span>throwing <tt class="classname">RunRecoveryException</tt>.</span>
|
||||
</p>
|
||||
<p>
|
||||
Be aware that there are some limitations/requirements if you want your various processes to
|
||||
coordinate recovery using this registration process:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
There can be only one environment handle per
|
||||
environment per process. In the case of multi-threaded
|
||||
processes, the environment handle must be shared across threads.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
All processes sharing the environment must use registration. If registration is
|
||||
not uniformly used across all participating processes, then you can see inconsistent results
|
||||
in terms of your application's ability to recognize that recovery must be run.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="recovery.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="hotfailover.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Recovery Procedures </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Using Hot Failovers</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
160
docs/gsg_txn/JAVA/autocommit.html
Normal file
160
docs/gsg_txn/JAVA/autocommit.html
Normal file
@@ -0,0 +1,160 @@
|
||||
<?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>Auto Commit</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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="abortresults.html" title="Aborting a Transaction" />
|
||||
<link rel="next" href="nestedtxn.html" title="Nested Transactions" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Auto Commit</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="abortresults.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="nestedtxn.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="autocommit"></a>Auto Commit</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
While transactions are frequently used to provide atomicity to
|
||||
multiple database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
operations, it is sometimes necessary to perform
|
||||
a single database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
operation under the control of a transaction.
|
||||
Rather than force you to obtain a transaction, perform the single
|
||||
write operation, and then either commit or abort the transaction,
|
||||
you can automatically group this sequence of events using
|
||||
<span class="emphasis"><em>auto commit</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
To use auto commit:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Open your environment and your databases
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
so that they support
|
||||
transactions. See <a href="enabletxn.html">Enabling Transactions</a>
|
||||
for details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Do not provide a transactional handle to the method that is
|
||||
performing the database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
write operation.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
Note that auto commit is not available for cursors. You must always
|
||||
open your cursor using a transaction if you want the cursor's
|
||||
operations to be transactional protected. See
|
||||
<a href="txncursor.html">Transactional Cursors</a> for details on using
|
||||
transactional cursors.
|
||||
</p>
|
||||
<p>
|
||||
For example, the following uses auto commit to perform the database write operation:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Open the database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
myDatabase = myEnv.openDatabase(null, // txn handle
|
||||
"sampleDatabase", // db file name
|
||||
null, // db name
|
||||
dbConfig);
|
||||
String keyString = "thekey";
|
||||
String dataString = "thedata";
|
||||
DatabaseEntry key =
|
||||
new DatabaseEntry(keyString.getBytes("UTF-8"));
|
||||
DatabaseEntry data =
|
||||
new DatabaseEntry(dataString.getBytes("UTF-8"));
|
||||
|
||||
// Perform the write. Because the database was opened to
|
||||
// support transactions, this write is performed using auto commit.
|
||||
myDatabase.put(null, key, data);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="abortresults.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="nestedtxn.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Aborting a Transaction </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Nested Transactions</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
336
docs/gsg_txn/JAVA/backuprestore.html
Normal file
336
docs/gsg_txn/JAVA/backuprestore.html
Normal file
@@ -0,0 +1,336 @@
|
||||
<?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>Backup Procedures</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="next" href="recovery.html" title="Recovery Procedures" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Backup Procedures</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="filemanagement.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="recovery.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="backuprestore"></a>Backup Procedures</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
<span class="emphasis"><em>Durability</em></span> is an important part of your
|
||||
transactional guarantees. It means that once a transaction has been
|
||||
successfully committed, your application will always see the results of that
|
||||
transaction.
|
||||
</p>
|
||||
<p>
|
||||
Of course, no software algorithm can guarantee durability in the face of physical data loss. Hard drives
|
||||
can fail, and if you have not copied your data to locations other than your primary disk drives,
|
||||
then you will lose data when those drives fail. Therefore, in order to truly obtain a durability
|
||||
guarantee, you need to ensure that any data stored on disk is backed up to secondary or alternative storage,
|
||||
such as secondary disk drives, or offline tapes.
|
||||
</p>
|
||||
<p>
|
||||
There are three different types of backups that you can
|
||||
perform with DB databases and log files. They are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Offline backups
|
||||
</p>
|
||||
<p>
|
||||
This type of backup is perhaps the easiest to perform as it
|
||||
involves simply copying database and log files to an
|
||||
offline storage area. It also gives you a snapshot of the
|
||||
database at a fixed, known point in time. However, you
|
||||
cannot perform this type of a backup while you are performing
|
||||
writes to the database.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Hot backups
|
||||
</p>
|
||||
<p>
|
||||
This type of backup gives you a snapshot of your database.
|
||||
Since your application can be writing to the database at the time that the
|
||||
snapshot is being taken, you do not necessarily know what
|
||||
the exact state of the database is for that given snapshot.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Incremental backups
|
||||
</p>
|
||||
<p>
|
||||
This type of backup refreshes a previously performed backup.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Once you have performed a backup, you can
|
||||
perform <span class="emphasis"><em>catastrophic recovery</em></span> to restore
|
||||
your databases from the backup. See
|
||||
<a href="recovery.html#catastrophicrecovery">Catastrophic Recovery</a>
|
||||
for more information.
|
||||
</p>
|
||||
<p>
|
||||
Note that you can also maintain a hot failover. See
|
||||
<a href="hotfailover.html">Using Hot Failovers</a>
|
||||
for more information.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="copyutilities"></a>About Unix Copy Utilities</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
If you are copying database files you must copy databases atomically,
|
||||
in multiples of the database page size. In other words, the reads made by
|
||||
the copy program must not be interleaved with writes by
|
||||
other threads of control, and the copy program must read the
|
||||
databases in multiples of the underlying database page size.
|
||||
Generally, this is not a problem because operating systems
|
||||
already make this guarantee and system utilities normally
|
||||
read in power-of-2 sized chunks, which are larger than the
|
||||
largest possible Berkeley DB database page size.
|
||||
</p>
|
||||
<p>
|
||||
On some platforms (most notably, some releases of Solaris), the copy utility (<tt class="literal">cp</tt>) was
|
||||
implemented using the <tt class="function">mmap()</tt> system call rather than the
|
||||
<tt class="function">read()</tt> system call. Because <tt class="function">mmap()</tt> did not make the same
|
||||
guarantee of read atomicity as did <tt class="function">read()</tt>, the <tt class="literal">cp</tt> utility
|
||||
could create corrupted copies of the databases.
|
||||
</p>
|
||||
<p>
|
||||
Also, some platforms have implementations of the <tt class="literal">tar</tt> utility that performs 10KB block
|
||||
reads by default. Even when an output block size is specified, the utility will still not read the
|
||||
underlying databases in multiples of the specified block size. Again, the result can be a corrupted backup.
|
||||
</p>
|
||||
<p>
|
||||
To fix these problems, use the <tt class="literal">dd</tt> utility instead of <tt class="literal">cp</tt> or
|
||||
<tt class="literal">tar</tt>. When you use <tt class="literal">dd</tt>, make sure you specify a block size that is
|
||||
equal to, or an even multiple of, your database page size. Finally, if you plan to use a system
|
||||
utility to copy database files, you may want to use a system call trace utility (for example,
|
||||
<tt class="literal">ktrace</tt> or <tt class="literal">truss</tt>) to make sure you are not using a I/O size that is
|
||||
smaller than your database page size. You can also use these utilities to make sure the system utility is
|
||||
not using a system call other than <tt class="function">read()</tt>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="standardbackup"></a>Offline Backups</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To create an offline backup:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Commit or abort all on-going transactions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Pause all database writes.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Force a checkpoint. See
|
||||
<a href="filemanagement.html#checkpoints">Checkpoints</a>
|
||||
for details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Copy all your database files to the backup location.
|
||||
<span>
|
||||
Note that you can simply copy all of the database
|
||||
files, or you can determine which database files
|
||||
have been written during the lifetime of the current
|
||||
logs. To do this, use either the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">Environment.getArchiveDatabases()</tt>,
|
||||
method
|
||||
</span>
|
||||
|
||||
or use the <span><b class="command">db_archive</b></span>
|
||||
command with the <tt class="literal">-s</tt> option.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
However, be aware that backing up just the modified databases only works if you have all of your
|
||||
log files. If you have been removing log files for any reason then using
|
||||
|
||||
<span>
|
||||
<tt class="methodname">getArchiveDatabases()</tt>,
|
||||
</span>
|
||||
|
||||
can result in an
|
||||
unrecoverable backup because you might not be notified of a database file that was modified.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Copy the <span class="emphasis"><em>last</em></span> log file to your backup location.
|
||||
Your log files are named
|
||||
<tt class="literal">log.<span class="emphasis"><em>xxxxxxxxxx</em></span></tt>,
|
||||
where <span class="emphasis"><em>xxxxxxxxxx</em></span> is a
|
||||
sequential number. The last log file is the file
|
||||
with the highest number.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="hotbackup"></a>Hot Backup</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To create a hot backup, you do not have to stop database
|
||||
operations. Transactions may be on-going and you can be writing
|
||||
to your database at the time of the backup. However, this means
|
||||
that you do not know exactly what the state of your database is
|
||||
at the time of the backup.
|
||||
</p>
|
||||
<p>
|
||||
You can use the <span><b class="command">db_hotbackup</b></span> command line utility to create a hot backup for you. This
|
||||
utility will (optionally) run a checkpoint and the copy all necessary files to a target directory.
|
||||
</p>
|
||||
<p>
|
||||
Alternatively, you can manually create a hot backup as follows:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Copy all your database files to the backup location.
|
||||
<span>
|
||||
Note that you can simply copy all of the database
|
||||
files, or you can determine which database files
|
||||
have been written during the lifetime of the current
|
||||
logs. To do this, use either the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">Environment.getArchiveDatabases()</tt>,
|
||||
</span>
|
||||
|
||||
or use the <span><b class="command">db_archive</b></span>
|
||||
command with the <tt class="literal">-s</tt> option.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Copy all logs to your backup location.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
It is important to copy your database files <span class="emphasis"><em>and
|
||||
then</em></span> your logs. In this way,
|
||||
you can complete or roll back any database operations that were only partially completed
|
||||
when you copied the databases.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="incrementalbackups"></a>Incremental Backups</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Once you have created a full backup (that is, either a
|
||||
offline or hot backup), you can create incremental backups.
|
||||
To do this, simply copy all of your currently existing log
|
||||
files to your backup location.
|
||||
</p>
|
||||
<p>
|
||||
Incremental backups do not require you to run a checkpoint
|
||||
or to cease database write operations.
|
||||
</p>
|
||||
<p>
|
||||
When you are working with incremental backups, remember
|
||||
that the greater the number of log files contained in
|
||||
your backup, the longer recovery will take.
|
||||
You should run full backups
|
||||
on some interval, and then do incremental backups on a shorter interval.
|
||||
How frequently you need to run a full backup
|
||||
is determined by the rate at which your databases change and
|
||||
how sensitive your application is to lengthy recoveries
|
||||
(should one be required).
|
||||
</p>
|
||||
<p>
|
||||
You can also shorten recovery time by running recovery against the backup as you take each incremental
|
||||
backup. Running recovery as you go means that there will be less work for DB to do if you should
|
||||
ever need to restore your environment from the backup.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="filemanagement.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="recovery.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 5. Managing DB Files </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Recovery Procedures</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
691
docs/gsg_txn/JAVA/blocking_deadlocks.html
Normal file
691
docs/gsg_txn/JAVA/blocking_deadlocks.html
Normal file
@@ -0,0 +1,691 @@
|
||||
<?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>Locks, Blocks, and Deadlocks</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="txnconcurrency.html" title="Chapter 4. Concurrency" />
|
||||
<link rel="next" href="lockingsubsystem.html" title="The Locking Subsystem" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Locks, Blocks, and Deadlocks</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnconcurrency.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Concurrency</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="lockingsubsystem.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="blocking_deadlocks"></a>Locks, Blocks, and Deadlocks</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
It is important to understand how locking works in a
|
||||
concurrent application before continuing with a description of
|
||||
the concurrency mechanisms DB makes available to you.
|
||||
Blocking and deadlocking have important performance implications
|
||||
for your application. Consequently, this section provides a
|
||||
fundamental description of these concepts, and how they affect
|
||||
DB operations.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="locks"></a>Locks</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When one thread of control wants to obtain access to an
|
||||
object, it requests a <span class="emphasis"><em>lock</em></span> for that
|
||||
object. This lock is what allows DB to provide your
|
||||
application with its transactional isolation guarantees by
|
||||
ensuring that:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
no other thread of control can read that object (in
|
||||
the case of an exclusive lock), and
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
no other thread of control can modify that object
|
||||
(in the case of an exclusive or non-exclusive lock).
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="lockresources"></a>Lock Resources</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When locking occurs, there are conceptually three resources
|
||||
in use:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
The locker.
|
||||
</p>
|
||||
<p>
|
||||
This is the thing that holds the lock. In a
|
||||
transactional application, the locker is a
|
||||
transaction handle.
|
||||
<span>
|
||||
For non-transactional operations, the locker is a cursor or a
|
||||
|
||||
|
||||
<span>Database or Store</span>
|
||||
|
||||
handle.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The lock.
|
||||
</p>
|
||||
<p>
|
||||
This is the actual data structure that locks
|
||||
the object. In DB, a locked
|
||||
object structure in the lock manager
|
||||
is representative of the object that
|
||||
is locked.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The locked object.
|
||||
</p>
|
||||
<p>
|
||||
The thing that your application
|
||||
actually wants to lock.
|
||||
In a DB
|
||||
application, the locked object is usually a
|
||||
<span>
|
||||
database page, which in turn contains
|
||||
multiple database entries (key and data).
|
||||
<span>
|
||||
However, for Queue databases,
|
||||
individual database records are locked.
|
||||
</span>
|
||||
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
You can configure how many total lockers, locks,
|
||||
and locked objects your
|
||||
application is allowed to support. See
|
||||
<a href="lockingsubsystem.html#configuringlock">Configuring the Locking Subsystem</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
The following figure shows a transaction handle,
|
||||
<tt class="literal">Txn A</tt>, that is holding a lock on
|
||||
database
|
||||
<span>page</span>
|
||||
|
||||
<tt class="literal">002</tt>. In this graphic, <tt class="literal">Txn
|
||||
A</tt> is the locker, and the locked object is
|
||||
<span>page</span>
|
||||
|
||||
<tt class="literal">002</tt>. Only a single lock is in use
|
||||
in this operation.
|
||||
</p>
|
||||
<div class="mediaobject">
|
||||
<img src="simplelock.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="locktypes"></a>Types of Locks</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB applications support both exclusive and
|
||||
non-exclusive locks. <span class="emphasis"><em>Exclusive
|
||||
locks</em></span> are granted when a
|
||||
locker wants to write to an object. For this reason,
|
||||
exclusive locks are also sometimes called
|
||||
<span class="emphasis"><em>write locks</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
An exclusive lock prevents any other locker from
|
||||
obtaining any sort of a lock on the object. This
|
||||
provides isolation by ensuring that no other locker can
|
||||
observe or modify an exclusively locked object until the locker is done
|
||||
writing to that object.
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em>Non-exclusive locks</em></span> are granted
|
||||
for read-only access. For this reason, non-exclusive
|
||||
locks are also sometimes called <span class="emphasis"><em>read
|
||||
locks</em></span>. Since multiple lockers can
|
||||
simultaneously hold read locks on the same
|
||||
object, read locks are also
|
||||
sometimes called <span class="emphasis"><em>shared locks</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
A non-exclusive lock prevents any other locker from
|
||||
modifying the locked object while the locker is still
|
||||
reading the object. This is how transactional cursors are able to
|
||||
achieve repeatable reads; by default, the
|
||||
cursor's transaction holds
|
||||
a read lock on any object that the cursor has examined until
|
||||
such a time as the transaction is committed
|
||||
or aborted.
|
||||
<span>
|
||||
You can avoid these read locks by using
|
||||
snapshot isolation. See <a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a>
|
||||
for details.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
In the following figure, <tt class="literal">Txn A</tt> and
|
||||
<tt class="literal">Txn B</tt> are both holding read locks on
|
||||
<span>page</span>
|
||||
|
||||
<tt class="literal">002</tt>, while <tt class="literal">Txn C</tt>
|
||||
is holding a write lock on
|
||||
<span>page</span>
|
||||
|
||||
<tt class="literal">003</tt>:
|
||||
</p>
|
||||
<div class="mediaobject">
|
||||
<img src="rwlocks1.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="locklifetime"></a>Lock Lifetime</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
A locker holds its locks until such a time as it does
|
||||
not need the lock any more. What this means is:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
A transaction holds any locks that it obtains
|
||||
until the transaction is committed or aborted.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
All non-transaction operations hold locks
|
||||
until such a time as the operation is completed.
|
||||
For cursor operations, the lock is held until the cursor is moved to a new position or
|
||||
closed.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="blocks"></a>Blocks</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Simply put, a thread of control is blocked when it attempts
|
||||
to obtain a lock, but that attempt is denied because some
|
||||
other thread of control holds a conflicting lock.
|
||||
Once blocked, the thread of control is temporarily unable
|
||||
to make any forward progress until the requested lock is
|
||||
obtained or the operation requesting the lock is
|
||||
abandoned.
|
||||
</p>
|
||||
<p>
|
||||
Be aware that when we talk about blocking, strictly
|
||||
speaking the thread is not what is attempting to obtain the
|
||||
lock. Rather, some object within the thread (such as a
|
||||
cursor) is attempting to obtain the
|
||||
lock. However, once a locker attempts to
|
||||
obtain a lock, the entire thread of control must pause until the lock
|
||||
request is in some way resolved.
|
||||
</p>
|
||||
<p>
|
||||
For example, if <tt class="literal">Txn A</tt> holds a write lock (an exclusive
|
||||
lock) on
|
||||
<span>object</span>
|
||||
|
||||
002, then if <tt class="literal">Txn B</tt> tries to obtain a read <span class="emphasis"><em>or</em></span> write lock on
|
||||
that
|
||||
<span>object,</span>
|
||||
|
||||
the thread of control in which <tt class="literal">Txn
|
||||
B</tt> is running
|
||||
is blocked:
|
||||
</p>
|
||||
<div class="mediaobject">
|
||||
<img src="writeblock.jpg" />
|
||||
</div>
|
||||
<p>
|
||||
However, if <tt class="literal">Txn A</tt> only holds a read
|
||||
lock (a shared lock) on
|
||||
<span>object</span>
|
||||
|
||||
<tt class="literal">002</tt>, then only those handles that attempt to obtain a
|
||||
write lock on that
|
||||
<span>object</span>
|
||||
|
||||
will block.
|
||||
</p>
|
||||
<div class="mediaobject">
|
||||
<img src="readblock.jpg" />
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
The previous description describes DB's default
|
||||
behavior when it cannot obtain a lock. It is
|
||||
possible to configure DB transactions so that
|
||||
they will not block. Instead, if a lock is
|
||||
unavailable, the application is immediately notified of a
|
||||
deadlock situation. See <a href="txnnowait.html">No Wait on Blocks</a>
|
||||
for more information.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="blockperformance"></a>Blocking and Application Performance</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Multi-threaded
|
||||
<span>
|
||||
and multi-process
|
||||
</span>
|
||||
applications typically perform better than simple
|
||||
single-threaded applications because the
|
||||
application can perform one part of its workload
|
||||
(updating
|
||||
<span>a database record, </span>
|
||||
|
||||
for example) while it is waiting for some other
|
||||
lengthy operation to complete (performing disk or
|
||||
network I/O, for example). This performance
|
||||
improvement is particularly noticeable if you use
|
||||
hardware that offers multiple CPUs, because the threads
|
||||
<span>
|
||||
and processes
|
||||
</span>
|
||||
can run simultaneously.
|
||||
</p>
|
||||
<p>
|
||||
That said, concurrent applications can see reduced
|
||||
workload throughput if their threads of control are
|
||||
seeing a large amount of lock contention. That is,
|
||||
if threads are blocking on lock requests, then that
|
||||
represents a performance penalty for your
|
||||
application.
|
||||
</p>
|
||||
<p>
|
||||
Consider once again the previous diagram of a blocked write lock request.
|
||||
In that diagram, <tt class="literal">Txn C</tt> cannot
|
||||
obtain its requested write lock because
|
||||
<tt class="literal">Txn A</tt> and <tt class="literal">Txn
|
||||
B</tt> are both already holding read locks on
|
||||
the requested
|
||||
<span>object.</span>
|
||||
|
||||
In this case, the thread in which
|
||||
<tt class="literal">Txn C</tt> is running will pause until
|
||||
such a time as <tt class="literal">Txn C</tt> either
|
||||
obtains its write lock, or the operation
|
||||
that is requesting the lock is abandoned.
|
||||
The fact that <tt class="literal">Txn
|
||||
C</tt>'s thread has temporarily halted all
|
||||
forward progress represents a performance penalty
|
||||
for your application.
|
||||
</p>
|
||||
<p>
|
||||
Moreover, any read locks that are requested while
|
||||
<tt class="literal">Txn C</tt> is waiting for its write
|
||||
lock will also block until such a time as
|
||||
<tt class="literal">Txn C</tt> has obtained and
|
||||
subsequently released its write lock.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="blockavoidance"></a>Avoiding Blocks</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Reducing lock contention is an important part of
|
||||
performance tuning your concurrent DB
|
||||
application. Applications that have multiple
|
||||
threads of control obtaining exclusive (write)
|
||||
locks are prone to contention issues. Moreover, as
|
||||
you increase the numbers of lockers and as you
|
||||
increase the time that a lock is held, you increase
|
||||
the chances of your application seeing lock contention.
|
||||
</p>
|
||||
<p>
|
||||
As you are designing your application, try to do
|
||||
the following in order to reduce lock contention:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Reduce the length of time your application
|
||||
holds locks.
|
||||
</p>
|
||||
<p>
|
||||
Shorter lived transactions will result in
|
||||
shorter lock lifetimes, which will in turn
|
||||
help to reduce lock contention.
|
||||
</p>
|
||||
<p>
|
||||
In addition, by default transactional cursors hold read
|
||||
locks until such a time as the transaction is completed.
|
||||
For this reason, try to minimize the time you keep
|
||||
transactional cursors opened, or reduce your isolation
|
||||
levels – see below.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If possible, access heavily accessed (read
|
||||
or write) items toward the end of the
|
||||
transaction. This reduces the amount of
|
||||
time that a heavily used
|
||||
<span>
|
||||
page
|
||||
</span>
|
||||
|
||||
is locked by the transaction.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Reduce your application's isolation guarantees.
|
||||
</p>
|
||||
<p>
|
||||
By reducing your isolation guarantees, you
|
||||
reduce the situations in which a lock can
|
||||
block another lock. Try using uncommitted reads
|
||||
for your read operations in order to
|
||||
prevent a read lock being blocked by a
|
||||
write lock.
|
||||
</p>
|
||||
<p>
|
||||
In addition, for cursors you can use degree
|
||||
2 (read committed) isolation, which causes
|
||||
the cursor to release its read locks as
|
||||
soon as it is done reading the record (as
|
||||
opposed to holding its read locks until the
|
||||
transaction ends).
|
||||
</p>
|
||||
<p>
|
||||
Be aware that reducing your
|
||||
isolation guarantees can have
|
||||
adverse consequences for your
|
||||
application. Before deciding
|
||||
to reduce your isolation, take
|
||||
care to examine your
|
||||
application's isolation
|
||||
requirements.
|
||||
For information on isolation
|
||||
levels, see
|
||||
<a href="isolation.html">Isolation</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Use snapshot isolation for
|
||||
read-only threads.
|
||||
</p>
|
||||
<p>
|
||||
Snapshot isolation causes the
|
||||
transaction to make a copy of the
|
||||
page on which it is holding a lock.
|
||||
When a reader makes a copy of a
|
||||
page, write locks can still be
|
||||
obtained for the original page.
|
||||
This eliminates entirely read-write
|
||||
contention.
|
||||
</p>
|
||||
<p>
|
||||
Snapshot isolation is described in
|
||||
<a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Consider your data access patterns.
|
||||
</p>
|
||||
<p>
|
||||
Depending on the nature of your application,
|
||||
this may be something that you can not
|
||||
do anything about. However, if it is
|
||||
possible to create your threads such that
|
||||
they operate only on non-overlapping
|
||||
portions of your database, then you can
|
||||
reduce lock contention because your
|
||||
threads will rarely (if ever) block on one another's
|
||||
locks.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
It is possible to configure DB's transactions
|
||||
so that they never wait on blocked lock requests.
|
||||
Instead, if they are blocked on a lock request,
|
||||
they will notify the application of a deadlock (see
|
||||
the next section).
|
||||
</p>
|
||||
<p>
|
||||
You configure this behavior on a transaction by
|
||||
transaction basis. See <a href="txnnowait.html">No Wait on Blocks</a> for more information.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="deadlocks"></a>Deadlocks</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
A deadlock occurs when two or more threads of control are
|
||||
blocked, each waiting on a resource held by the other
|
||||
thread. When this happens, there is no
|
||||
possibility of the threads ever making forward progress
|
||||
unless some outside agent takes action to break the
|
||||
deadlock.
|
||||
</p>
|
||||
<p>
|
||||
For example, if
|
||||
<tt class="literal">Txn A</tt> is
|
||||
blocked by <tt class="literal">Txn B</tt> at the same time
|
||||
<tt class="literal">Txn B</tt> is blocked by <tt class="literal">Txn
|
||||
A</tt> then the threads of control containing
|
||||
<tt class="literal">Txn A</tt> and <tt class="literal">Txn B</tt> are
|
||||
deadlocked; neither thread can make
|
||||
any forward progress because neither thread will ever release the lock
|
||||
that is blocking the other thread.
|
||||
</p>
|
||||
<div class="mediaobject">
|
||||
<img src="deadlock.jpg" />
|
||||
</div>
|
||||
<p>
|
||||
When two threads of control deadlock, the only
|
||||
solution is to have a mechanism external to the two threads
|
||||
capable of recognizing the deadlock and notifying at least
|
||||
one thread that it is in a deadlock situation.
|
||||
Once notified, a thread of
|
||||
control must abandon the attempted operation in order to
|
||||
resolve the deadlock.
|
||||
|
||||
<span>
|
||||
DB's locking subsystem offers a deadlock notification
|
||||
mechanism. See
|
||||
<a href="lockingsubsystem.html#configdeadlkdetect">Configuring Deadlock Detection</a>
|
||||
for more information.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Note that when one locker in a thread of control is blocked
|
||||
waiting on a lock held by another locker in that same
|
||||
thread of the control, the thread is said to be
|
||||
<span class="emphasis"><em>self-deadlocked</em></span>.
|
||||
</p>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="deadlockavoidance"></a>Deadlock Avoidance</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The things that you do to avoid lock contention also
|
||||
help to reduce deadlocks (see <a href="blocking_deadlocks.html#blockavoidance">Avoiding Blocks</a>).
|
||||
|
||||
<span>
|
||||
Beyond that, you can also do the following in order to
|
||||
avoid deadlocks:
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Make sure all threads access data in the same
|
||||
order as all other threads. So long as threads
|
||||
lock database pages
|
||||
in the same basic order, there is no
|
||||
possibility of a deadlock (threads can still
|
||||
block, however).
|
||||
</p>
|
||||
<p>
|
||||
Be aware that if you are using secondary databases (indices), it is not possible to obtain
|
||||
locks in a consistent order because you cannot predict the order in which locks are obtained
|
||||
in secondary databases. If you are writing a concurrent application and you are using
|
||||
secondary databases, you must be prepared to handle deadlocks.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you are using BTrees in which you are
|
||||
constantly adding and then deleting data, turn
|
||||
Btree reverse split off. See
|
||||
<a href="reversesplit.html">Reverse BTree Splits</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Declare a read/modify/write lock for those
|
||||
situations where you are reading a record in
|
||||
preparation of modifying and then writing the
|
||||
record. Doing this causes DB to give your
|
||||
read operation a write lock. This means that no
|
||||
other thread of control can share a read lock
|
||||
(which might cause contention), but it also
|
||||
means that the writer thread will not have to
|
||||
wait to obtain a write lock when it is ready to
|
||||
write the modified data back to the database.
|
||||
</p>
|
||||
<p>
|
||||
For information on declaring
|
||||
read/modify/write locks, see
|
||||
<a href="readmodifywrite.html">Read/Modify/Write</a>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnconcurrency.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="lockingsubsystem.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 4. Concurrency </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> The Locking Subsystem</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/gsg_txn/JAVA/deadlock.jpg
Normal file
BIN
docs/gsg_txn/JAVA/deadlock.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
892
docs/gsg_txn/JAVA/enabletxn.html
Normal file
892
docs/gsg_txn/JAVA/enabletxn.html
Normal file
@@ -0,0 +1,892 @@
|
||||
<?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>Chapter 2. Enabling Transactions</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="perftune-intro.html" title="Performance Tuning" />
|
||||
<link rel="next" href="envopen.html" title="Opening a Transactional Environment and Store or Database " />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 2. Enabling Transactions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="perftune-intro.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="envopen.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="enabletxn"></a>Chapter 2. Enabling Transactions</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="enabletxn.html#environments">Environments</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#filenaming">File Naming</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#errorsupport">Error Support</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#sharedmemory">Shared Memory Regions</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#security">Security Considerations</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="envopen.html">Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
In order to use transactions with your application, you must turn them
|
||||
on. To do this you must:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Use an
|
||||
environment (see <a href="enabletxn.html#environments">Environments</a> for details).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Turn on transactions for your environment.
|
||||
|
||||
<span>
|
||||
You do this by using the
|
||||
<tt class="methodname">EnvironmentConfig.setTransactional()</tt>
|
||||
method.
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
Note that initializing the transactional subsystem implies that
|
||||
the logging subsystem is also initialized. Also, note that
|
||||
if you do not initialize transactions when you first create
|
||||
your environment, then you cannot use transactions for that
|
||||
environment after that. This is because DB
|
||||
allocates certain structures needed for transactional
|
||||
locking that are not available if the environment is
|
||||
created without transactional support.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Initialize the in-memory cache by
|
||||
|
||||
|
||||
<span>
|
||||
passing <tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setInitializeCache()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Initialize the locking subsystem. This is what provides locking for concurrent applications. It also is used
|
||||
to perform deadlock detection. See <a href="txnconcurrency.html">Concurrency</a>
|
||||
for more information.
|
||||
</p>
|
||||
<p>
|
||||
You initialize the locking subsystem by
|
||||
|
||||
|
||||
<span>
|
||||
passing <tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setInitializeLocking()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you are using the DPL, transaction-enable your stores.
|
||||
You do this by using the
|
||||
<tt class="methodname">StoreConfig.setTransactional() method.</tt>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span>
|
||||
Transaction-enable your databases.
|
||||
</span>
|
||||
<span>
|
||||
If you are using the base API, transaction-enable your databases.
|
||||
</span>
|
||||
You do this by
|
||||
<span>
|
||||
using the
|
||||
<tt class="methodname">DatabaseConfig.setTransactional()</tt>
|
||||
method, and then opening the database from within a transaction.
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
Note that the common practice is for auto commit to be used to
|
||||
transaction-protect the database open. To use auto-commit, you
|
||||
must still enable transactions as described here, but you do
|
||||
not have to explicitly use a transaction when you open your
|
||||
database. An example of this is given in the next section.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="environments"></a>Environments</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
For simple DB applications, environments are optional. However, in
|
||||
order to transaction protect your database operations, you must use an
|
||||
environment.
|
||||
</p>
|
||||
<p>
|
||||
An <span class="emphasis"><em>environment</em></span>, represents an
|
||||
encapsulation of one or more databases and any associated log and
|
||||
region files. They are used to support multi-threaded
|
||||
and multi-process applications by allowing different threads of
|
||||
control to share the in-memory cache, the locking tables, the
|
||||
logging subsystem, and the file namespace. By sharing these things,
|
||||
your concurrent application is more efficient than if each thread
|
||||
of control had to manage these resources on its own.
|
||||
</p>
|
||||
<p>
|
||||
By default all DB databases are backed by files on disk. In
|
||||
addition to these files, transactional DB applications create
|
||||
logs that are also by default stored on disk (they can optionally
|
||||
be backed using shared memory). Finally, transactional
|
||||
DB applications also create and use shared-memory regions that
|
||||
are also typically backed by the filesystem. But like databases and
|
||||
logs, the regions can be maintained strictly in-memory if your
|
||||
application requires it. For an example of an application that
|
||||
manages all environment files in-memory, see
|
||||
|
||||
<span><a href="inmem_txnexample_java.html">Base API In-Memory Transaction Example</a>.</span>
|
||||
|
||||
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="filenaming"></a>File Naming</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to operate, your DB application must be able to
|
||||
locate its database files, log files, and region files. If these
|
||||
are stored in the filesystem, then you must tell DB where
|
||||
they are located (a number of mechanisms exist that allow you to
|
||||
identify the location of these files – see below). Otherwise,
|
||||
by default they are located in the current working directory.
|
||||
</p>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="envhome"></a>Specifying the Environment Home Directory</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The environment home directory is used to determine where
|
||||
DB files are located. Its location
|
||||
is identified using one of the following mechanisms, in the
|
||||
following order of priority:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
If no information is given as to where to put the
|
||||
environment home, then the current working
|
||||
directory is used.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If a home directory is specified on the
|
||||
|
||||
|
||||
<tt class="methodname">Environment()</tt>
|
||||
|
||||
<span>constructor,</span>
|
||||
then that location is always used for the environment
|
||||
home.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If a home directory is not supplied to
|
||||
|
||||
|
||||
<span><tt class="methodname">Environment()</tt>, </span>
|
||||
then the directory identified by the <tt class="literal">DB_HOME</tt> environment variable
|
||||
is used <span class="emphasis"><em>if</em></span> you specify
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to either the
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironment()</tt>
|
||||
or
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironmentRoot()</tt>
|
||||
method. Both methods allow you to identify the
|
||||
path to the environment's home directory
|
||||
using <tt class="literal">DB_HOME</tt>. However,
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironmentRoot()</tt>
|
||||
is honored only if the process is run with root or administrative privileges.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="filelocation"></a>Specifying File Locations</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
By default, all DB files are created relative to the environment
|
||||
home directory. For example, suppose your environment home is in
|
||||
<tt class="literal">/export/myAppHome</tt>. Also suppose you name your database
|
||||
<span><tt class="literal">data/myDatabase.db</tt>.</span>
|
||||
|
||||
Then in this case, the database is placed in:
|
||||
<span><tt class="literal">/export/myAppHome/data/myDatabase.db</tt>.</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
That said, DB always defers to absolute pathnames.
|
||||
This means that if you provide an absolute filename when you
|
||||
name your database, then that file is <span class="emphasis"><em>not</em></span>
|
||||
placed relative to the environment home directory. Instead, it
|
||||
is placed in the exact location that you specified for the
|
||||
filename.
|
||||
</p>
|
||||
<p>
|
||||
On UNIX systems, an absolute pathname is a name that begins with a
|
||||
forward slash ('/'). On Windows systems, an absolute pathname is a
|
||||
name that begins with one of the following:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
A backslash ('\').
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Any alphabetic letter, followed by a colon (':'), followed
|
||||
by a backslash ('\').
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Try not to use absolute path names for your
|
||||
environment's files. Under certain recovery scenarios, absolute path names can
|
||||
render your environment unrecoverable. This occurs if you are attempting to recover
|
||||
you environment on a system that does not support the absolute path name that you used.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="splittingdata"></a>Identifying Specific File Locations</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
As described in the previous sections, DB will place all its
|
||||
files in or relative to the environment home directory.
|
||||
You can also cause a
|
||||
specific database file to be placed in a particular location by
|
||||
using an absolute path name for its name. In this
|
||||
situation, the environment's home directory is not
|
||||
considered when naming the file.
|
||||
</p>
|
||||
<p>
|
||||
It is frequently desirable to place database, log, and region files on separate
|
||||
disk drives. By spreading I/O across multiple drives, you
|
||||
can increase parallelism and improve throughput.
|
||||
Additionally, by placing log files and database files on
|
||||
separate drives, you improve your application's
|
||||
reliability by providing your application with a greater
|
||||
chance of surviving a disk failure.
|
||||
</p>
|
||||
<p>
|
||||
You can cause DB's files to be placed in specific
|
||||
locations using the following mechanisms:
|
||||
</p>
|
||||
<div class="informaltable">
|
||||
<table border="1" width="80%">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>File Type</th>
|
||||
<th>To Override</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>database files</td>
|
||||
<td>
|
||||
<p>
|
||||
You can cause database files to be created
|
||||
in a directory other than the
|
||||
environment home by using the
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.addDataDir()</tt>
|
||||
method.
|
||||
The directory identified
|
||||
here must exist. If a relative path is
|
||||
provided, then the directory location is
|
||||
resolved relative to the environment's home
|
||||
directory.
|
||||
</p>
|
||||
<p>
|
||||
This method modifies the directory
|
||||
used for database files created and managed by
|
||||
a single environment handle; it does not
|
||||
configure the entire environment.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
You can also set a default data location that is used by
|
||||
the entire environment by using the
|
||||
<tt class="literal">set_data_dir</tt> parameter
|
||||
in the environment's <tt class="literal">DB_CONFIG</tt> file.
|
||||
Note that the <tt class="literal">set_data_dir</tt>
|
||||
parameter overrides any value set by the
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.addDataDir()</tt>
|
||||
method.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Log files</td>
|
||||
<td>
|
||||
<p>
|
||||
You can cause log files to be created
|
||||
in a directory other than the environment home
|
||||
directory by using the
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.LogDirectory()</tt>
|
||||
method. The directory identified
|
||||
here must exist. If a relative path is
|
||||
provided, then the directory location is
|
||||
resolved relative to the environment's home
|
||||
directory.
|
||||
</p>
|
||||
<p>
|
||||
This method modifies the directory
|
||||
used for database files created and managed by
|
||||
a single environment handle; it does not
|
||||
configure the entire environment.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
You can also set a default log file location that is used by
|
||||
the entire environment by using the
|
||||
<tt class="literal">set_lg_dir</tt> parameter
|
||||
in the environment's <tt class="literal">DB_CONFIG</tt> file.
|
||||
Note that the <tt class="literal">set_lg_dir</tt>
|
||||
parameter overrides any value set by the
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.LogDirectory()</tt>
|
||||
method.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Region files</td>
|
||||
<td>
|
||||
If backed by the filesystem, region
|
||||
files are always placed in the environment home
|
||||
directory.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
Note that the <tt class="literal">DB_CONFIG</tt> must reside in the
|
||||
environment home directory. Parameters are specified in it one
|
||||
parameter to a line. Each parameter is followed by a space,
|
||||
which is followed by the parameter value. For example:
|
||||
</p>
|
||||
<pre class="programlisting"> set_data_dir /export1/db/env_data_files </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="errorsupport"></a>Error Support</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To simplify error handling and to aid in application debugging, environments offer several useful
|
||||
methods.
|
||||
|
||||
<span>Note that many of these
|
||||
methods are identical to the error handling methods available for the
|
||||
|
||||
|
||||
<span>DatabaseConfig</span>
|
||||
|
||||
<span>class.</span>
|
||||
|
||||
</span>
|
||||
|
||||
They are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.setErrorStream()</tt>
|
||||
</p>
|
||||
<p>
|
||||
Sets the
|
||||
|
||||
<span>Java <tt class="classname">OutputStream</tt></span>
|
||||
to be used for displaying error messages issued by the DB library.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.setErrorHandler()</tt>
|
||||
</p>
|
||||
<p>
|
||||
Defines the message handler that is called when an error message is
|
||||
issued by DB. The error prefix and message are passed to
|
||||
this callback. It is up to the application to display this
|
||||
information correctly.
|
||||
</p>
|
||||
<p>
|
||||
Note that the message handler must be an implementation of the
|
||||
<tt class="classname">com.sleepycat.db.ErrorHandler</tt>
|
||||
interface.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.setErrorPrefix()</tt>
|
||||
</p>
|
||||
<p>
|
||||
Sets the prefix used to for any error messages issued by the
|
||||
DB library.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="sharedmemory"></a>Shared Memory Regions</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The subsystems that you enable for an environment (in our case,
|
||||
transaction, logging, locking, and the memory pool)
|
||||
are described by one or more regions. The regions contain all of the
|
||||
state information that needs to be shared among threads and/or
|
||||
processes using the environment.
|
||||
</p>
|
||||
<p>
|
||||
Regions may be backed by the file system, by heap memory, or by
|
||||
system shared memory.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
When DB dynamically obtains memory, it uses memory outside of the JVM. Normally the amount of memory
|
||||
that DB obtains is trivial, a few bytes here and there, so you might not notice it. However, if
|
||||
heap or system memory is used to back your region files, then this can represent a significant amount of
|
||||
memory being used by DB above and beyond the memory required by the JCM process. As a result, the
|
||||
JVM process may appear to be using more memory than you told the process it could use.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="filebackedregions"></a>Regions Backed by Files</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
By default, shared memory regions are created as files in the environment's
|
||||
home directory (<span class="emphasis"><em>not</em></span> the environment's data
|
||||
directory). If it is available, the POSIX <tt class="literal">mmap</tt>
|
||||
interface is used to map these files into your application's
|
||||
address space. If <tt class="literal">mmap</tt>
|
||||
is not available, then the UNIX <tt class="literal">shmget</tt> interfaces
|
||||
are used instead (again, if they are available).
|
||||
</p>
|
||||
<p>
|
||||
In this default case, the region files are named
|
||||
<tt class="literal">__db.###</tt>
|
||||
(for example, <tt class="literal">__db.001</tt>, <tt class="literal">__db.002</tt>,
|
||||
and so on).
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="heapbackedregions"></a>Regions Backed by Heap Memory</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If heap memory is used to back your shared memory regions,
|
||||
the environment may only be
|
||||
accessed by a single process, although that process may be
|
||||
multi-threaded. In this case, the regions are managed only in
|
||||
memory, and they are not written to the filesystem. You
|
||||
indicate that heap memory is to be used for the region files by
|
||||
specifying
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setPrivate()</tt>
|
||||
method.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
(For an example of an entirely in-memory transactional
|
||||
application, see
|
||||
|
||||
<span>
|
||||
<a href="inmem_txnexample_java.html">Base API In-Memory Transaction Example</a>.)
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect3" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h4 class="title"><a id="systembackedregions"></a>Regions Backed by System Memory</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Finally, you can cause system memory to be used for your
|
||||
regions instead of memory-mapped files. You do this by providing
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setSystemMemory()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
When region files are backed by system memory, DB creates a
|
||||
single file in the environment's home directory. This file
|
||||
contains information necessary to identify the system shared
|
||||
memory in use by the environment. By creating this file, DB
|
||||
enables multiple processes to share the environment.
|
||||
</p>
|
||||
<p>
|
||||
The system memory that is used is architecture-dependent. For
|
||||
example, on systems supporting X/Open-style shared memory
|
||||
interfaces, such as UNIX systems, the <tt class="literal">shmget(2)</tt>
|
||||
and related System V IPC interfaces are used.
|
||||
|
||||
<span>
|
||||
|
||||
Additionally, VxWorks systems use system memory. In these cases,
|
||||
an initial segment ID must be specified by the application to
|
||||
ensure that applications do not overwrite each other's
|
||||
environments, so that the number of segments created does not
|
||||
grow without bounds. See the
|
||||
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.setSegmentId()</tt>
|
||||
method for more information.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
On Windows platforms, the use of system memory for the region files
|
||||
is problematic because the operating system uses reference counting
|
||||
to clean up shared objects in the paging file automatically. In
|
||||
addition, the default access permissions for shared objects are
|
||||
different from files, which may cause problems when an environment
|
||||
is accessed by multiple processes running as different users. See
|
||||
<a href="" target="_top">Windows notes</a>
|
||||
or more information.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="security"></a>Security Considerations</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When using environments, there are some security considerations to
|
||||
keep in mind:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Database environment permissions
|
||||
</p>
|
||||
<p>
|
||||
The directory used for the environment
|
||||
should have its permissions set to ensure that files in the
|
||||
environment are not accessible to users without appropriate
|
||||
permissions. Applications that add to the user's permissions
|
||||
(for example, UNIX <tt class="literal">setuid</tt> or
|
||||
<tt class="literal">setgid</tt> applications), must be
|
||||
carefully checked to not permit illegal use of those
|
||||
permissions such as general file access in the environment
|
||||
directory.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Environment variables
|
||||
</p>
|
||||
<p>
|
||||
Setting
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> for <tt class="methodname">EnvironmentConfig.setUseEnvironment()</tt>
|
||||
or
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironmentRoot()</tt>
|
||||
</span>
|
||||
|
||||
so that environment variables can be used during file naming
|
||||
can be dangerous. Setting those flags in DB
|
||||
applications with additional permissions (for example, UNIX
|
||||
<tt class="literal">setuid</tt> or <tt class="literal">setgid</tt>
|
||||
applications) could potentially allow users
|
||||
to read and write databases to which they would not normally
|
||||
have access.
|
||||
</p>
|
||||
<p>
|
||||
For example, suppose you write a DB application
|
||||
that runs <tt class="literal">setuid</tt>. This means that
|
||||
when the application runs, it does so under a
|
||||
userid different than that of the application's caller.
|
||||
This is especially problematic if the application is
|
||||
granting stronger privileges to a user than the user
|
||||
might ordinarily have.
|
||||
</p>
|
||||
<p>
|
||||
Now, if
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> is specified
|
||||
for <tt class="methodname">EnvironmentConfig.setUseEnvironment()</tt>
|
||||
or
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironmentRoot()</tt>,
|
||||
</span>
|
||||
|
||||
|
||||
then the environment that the application is
|
||||
using is modifiable using the
|
||||
<tt class="literal">DB_HOME</tt> environment variable. In
|
||||
this scenario, if the uid used by the application has
|
||||
sufficiently broad privileges, then the application's caller
|
||||
can read and/or write databases owned by another user
|
||||
simply by setting his
|
||||
<tt class="literal">DB_HOME</tt> environment variable to the
|
||||
environment used by that other user.
|
||||
</p>
|
||||
<p>
|
||||
Note that this scenario need not be malicious; the
|
||||
wrong environment could be used by the application
|
||||
simply by inadvertently specifying the wrong path to
|
||||
<tt class="literal">DB_HOME</tt>.
|
||||
</p>
|
||||
<p>
|
||||
As always, you should use <tt class="literal">setuid</tt>
|
||||
sparingly, if at all. But if you do use
|
||||
<tt class="literal">setuid</tt>, then you should refrain from
|
||||
specifying
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> for <tt class="methodname">EnvironmentConfig.setUseEnvironment()</tt>
|
||||
or
|
||||
<tt class="methodname">EnvironmentConfig.setUseEnvironmentRoot()</tt>
|
||||
</span>
|
||||
for the environment open. And, of course, if you must
|
||||
use <tt class="literal">setuid</tt>, then make sure you use
|
||||
the weakest uid possible – preferably one that is
|
||||
used only by the application itself.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
File permissions
|
||||
</p>
|
||||
<p>
|
||||
By default, DB always creates database and log files readable and
|
||||
writable by the owner and the group (that is,
|
||||
<tt class="literal">S_IRUSR</tt>,
|
||||
<tt class="literal">S_IWUSR</tt>, <tt class="literal">S_IRGRP</tt> and
|
||||
<tt class="literal">S_IWGRP</tt>; or octal mode 0660 on historic
|
||||
UNIX systems). The group ownership of created files is based
|
||||
on the system and directory defaults, and is not further
|
||||
specified by DB.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Temporary backing files
|
||||
</p>
|
||||
<p>
|
||||
If an unnamed database is created and the cache is too small
|
||||
to hold the database in memory, Berkeley DB will create a
|
||||
temporary physical file to enable it to page the database to
|
||||
disk as needed. In this case, environment variables such as
|
||||
<tt class="literal">TMPDIR</tt> may be used to specify the
|
||||
location of that temporary file. Although temporary backing
|
||||
files are created readable and writable by the owner only
|
||||
(<tt class="literal">S_IRUSR</tt> and <tt class="literal">S_IWUSR</tt>,
|
||||
or octal mode 0600 on historic UNIX systems), some
|
||||
filesystems may not sufficiently protect temporary files
|
||||
created in random directories from improper access. To be
|
||||
absolutely safe, applications storing sensitive data in
|
||||
unnamed databases should use the
|
||||
|
||||
|
||||
<tt class="methodname">EnvironmentConfig.setTemporaryDirectory()</tt>
|
||||
method to specify a temporary directory with known permissions.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="perftune-intro.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="envopen.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Performance Tuning </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
209
docs/gsg_txn/JAVA/envopen.html
Normal file
209
docs/gsg_txn/JAVA/envopen.html
Normal file
@@ -0,0 +1,209 @@
|
||||
<?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>Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</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="enabletxn.html" title="Chapter 2. Enabling Transactions" />
|
||||
<link rel="previous" href="enabletxn.html" title="Chapter 2. Enabling Transactions" />
|
||||
<link rel="next" href="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="enabletxn.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 2. Enabling Transactions</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="usingtxns.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="envopen"></a>Opening a Transactional Environment and
|
||||
|
||||
<span>Store or Database</span>
|
||||
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To enable transactions for your environment, you must initialize the
|
||||
transactional subsystem. Note that doing this also initializes the
|
||||
logging subsystem. In addition, you must initialize the memory pool
|
||||
(in-memory cache). Frequently, but not always, you will also
|
||||
initialize the locking subsystem.
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
For example, to do this with the DPL:
|
||||
</span>
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.StoreConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
EntityStore myStore = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
StoreConfig storeConfig = new StoreConfig();
|
||||
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
storeConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
myStore = new EntityStore(myEnv, "EntityStore", storeConfig);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
<p>
|
||||
And when using the base API:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
<p>
|
||||
You then can use the <tt class="classname">Environment</tt> handle to open
|
||||
your database(s) using <tt class="methodname">Environment.openDatabase()</tt>.
|
||||
Note that when you do this, you must set
|
||||
<tt class="methodname">DatabaseConfig.setTransactional()</tt>
|
||||
to <tt class="literal">true</tt>. Note that in effect this causes the
|
||||
database open to be transactional protected because it results in
|
||||
auto commit being used for the open (if a transaction is not explicitly
|
||||
used to protect the open).
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
<b class="userinput"><tt>import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.DatabaseConfig;</tt></b>
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
<b class="userinput"><tt>Database myDatabase = null;</tt></b>
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
<b class="userinput"><tt>// Open the database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
myDatabase = myEnv.openDatabase(null, // txn handle
|
||||
"sampleDatabase", // db file name
|
||||
null, // db name
|
||||
dbConfig);</tt></b>
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Never close a database <span> or
|
||||
store </span> that has active transactions. Make sure
|
||||
all transactions are resolved (either committed or aborted)
|
||||
before closing the database.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="enabletxn.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="enabletxn.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="usingtxns.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 2. Enabling Transactions </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 3. Transaction Basics</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
484
docs/gsg_txn/JAVA/filemanagement.html
Normal file
484
docs/gsg_txn/JAVA/filemanagement.html
Normal file
@@ -0,0 +1,484 @@
|
||||
<?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>Chapter 5. Managing DB Files</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="reversesplit.html" title="Reverse BTree Splits" />
|
||||
<link rel="next" href="backuprestore.html" title="Backup Procedures" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 5. Managing DB Files</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="reversesplit.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="backuprestore.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="filemanagement"></a>Chapter 5. Managing DB Files</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="filemanagement.html#checkpoints">Checkpoints</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="backuprestore.html">Backup Procedures</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#copyutilities">About Unix Copy Utilities</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#standardbackup">Offline Backups</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#hotbackup">Hot Backup</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#incrementalbackups">Incremental Backups</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="recovery.html">Recovery Procedures</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="recovery.html#normalrecovery">Normal Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="recovery.html#catastrophicrecovery">Catastrophic Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="architectrecovery.html">Designing Your Application for Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="architectrecovery.html#multithreadrecovery">Recovery for Multi-Threaded Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="architectrecovery.html#multiprocessrecovery">Recovery in Multi-Process Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="hotfailover.html">Using Hot Failovers</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="logfileremoval.html">Removing Log Files</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="logconfig.html">Configuring the Logging Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logfilesize">Setting the Log File Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logregionsize">Configuring the Logging Region Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logbuffer">Setting the In-Memory Log Buffer Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
DB is capable of storing several types of files on disk:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Data files, which contain the actual data in your database.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Log files, which contain information required to recover your
|
||||
database in the event of a system or application failure.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Region files, which contain information necessary for the
|
||||
overall operation of your application.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Temporary files, which are created only under certain special circumstances. These files never need to
|
||||
be backed up or otherwise managed and so they are not a consideration for the topics described in this
|
||||
chapter. See <a href="enabletxn.html#security">Security Considerations</a>
|
||||
for more information on temporary files.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Of these, you must manage your data and log files by ensuring that they
|
||||
are backed up. You should also pay attention to the amount of disk space
|
||||
your log files are consuming, and periodically remove any unneeded
|
||||
files. Finally, you can optionally tune your logging subsystem to best
|
||||
suit your application's needs and requirements.
|
||||
These topics are discussed in this chapter.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="checkpoints"></a>Checkpoints</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before we can discuss DB file management, we need to
|
||||
describe checkpoints. When databases are modified (that is, a
|
||||
transaction is committed), the modifications are recorded in
|
||||
DB's logs, but they are <span class="emphasis"><em>not</em></span>
|
||||
necessarily reflected in the actual database files on disk.
|
||||
</p>
|
||||
<p>
|
||||
This means that as time goes on, increasingly
|
||||
more data is contained in your log files that is not
|
||||
contained in your data files. As a result, you must keep more
|
||||
log files around than you might actually need. Also, any
|
||||
recovery run from your log files will take increasingly longer
|
||||
amounts of time, because there is more data in the log files
|
||||
that must be reflected back into the data files during the
|
||||
recovery process.
|
||||
</p>
|
||||
<p>
|
||||
You can reduce these problems by periodically
|
||||
running a checkpoint against your environment. The checkpoint:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Flushes dirty pages from the in-memory cache. This means that data modifications found in your
|
||||
in-memory cache are written to the database files on disk. Note that a checkpoint also causes data
|
||||
dirtied by an uncommitted transaction to also be written to your database files on disk. In this latter
|
||||
case, DB's normal recovery is used to remove any such modifications that were subsequently
|
||||
abandoned by your application using a transaction abort.
|
||||
</p>
|
||||
<p>
|
||||
Normal recovery is describe in <a href="recovery.html">Recovery Procedures</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Writes a checkpoint record.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Flushes the log. This causes all log data that has not yet been written to disk to be written.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Writes a list of open databases.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
There are several ways to run a checkpoint. One way is to use
|
||||
the <span><b class="command">db_checkpoint</b></span> command line utility. (Note, however, that this command line utility
|
||||
cannot be used if your environment was opened using
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setPrivate()</tt>.)
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
You can also run a thread that periodically checkpoints your
|
||||
environment for you by calling the
|
||||
|
||||
|
||||
<tt class="methodname">Environment.checkpoint()</tt>
|
||||
method.
|
||||
</p>
|
||||
<p>
|
||||
Note that you can prevent a checkpoint from occurring unless more
|
||||
than a specified amount of log data has been written since the
|
||||
last checkpoint. You can also prevent the checkpoint from
|
||||
running unless more than a specified amount of time has
|
||||
occurred since the last checkpoint. These conditions are
|
||||
particularly interesting if you have multiple threads
|
||||
<span>or processes</span>
|
||||
running checkpoints.
|
||||
</p>
|
||||
<p>
|
||||
For configuration information, see the
|
||||
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/java/com/sleepycat/db/CheckpointConfig.html" target="_top">
|
||||
CheckpointConfig Javadoc page.
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Note that running checkpoints can be quite expensive. DB must
|
||||
flush every dirty page to the backing database files. On the
|
||||
other hand, if you do not run checkpoints often enough, your
|
||||
recovery time can be unnecessarily long and you may be using more
|
||||
disk space than you really need. Also, you cannot remove log files
|
||||
until a checkpoint is run. Therefore, deciding how frequently
|
||||
to run a checkpoint is one of the most
|
||||
common tuning activity for DB applications.
|
||||
</p>
|
||||
<p>
|
||||
For example, the following class performs a checkpoint every 60 seconds, so long as 500 kb of logging data has been
|
||||
written since the last checkpoint:
|
||||
</p>
|
||||
<pre class="programlisting"><span>package db.txn;</span>
|
||||
|
||||
import com.sleepycat.db.CheckpointConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
|
||||
public class CheckPointer extends Thread
|
||||
{
|
||||
private CheckpointConfig cpc = new CheckpointConfig();
|
||||
private Environment myEnv = null;
|
||||
private static boolean canRun = true;
|
||||
|
||||
|
||||
// Constructor.
|
||||
CheckPointer(Environment env) {
|
||||
myEnv = env;
|
||||
// Run a checkpoint only if 500 kbytes of log data has been
|
||||
// written.
|
||||
cpc.setKBytes(500);
|
||||
}
|
||||
|
||||
// Thread method that performs a checkpoint every
|
||||
// 60 seconds
|
||||
public void run () {
|
||||
while (canRun) {
|
||||
try {
|
||||
myEnv.checkpoint(cpc);
|
||||
sleep(60000);
|
||||
} catch (DatabaseException de) {
|
||||
System.err.println("Checkpoint error: " +
|
||||
de.toString());
|
||||
} catch (InterruptedException e) {
|
||||
// Should never get here
|
||||
System.err.println("got interrupted exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopRunning() {
|
||||
canRun = false;
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
And you use this class as follows. Note that we add the call to shutdown the checkpoint thread in our application's
|
||||
shutdown code:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
|
||||
public class TryCheckPoint {
|
||||
|
||||
private static String myEnvPath = "./";
|
||||
|
||||
private static Environment myEnv = null;
|
||||
|
||||
|
||||
private static void usage() {
|
||||
System.out.println("TxnGuide [-h <env directory>]");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
// Parse the arguments list
|
||||
parseArgs(args);
|
||||
// Open the environment and databases
|
||||
openEnv();
|
||||
|
||||
// Start the checkpoint thread
|
||||
CheckPointer cp = new CheckPointer(myEnv);
|
||||
cp.start();
|
||||
|
||||
//////////////////////////////////
|
||||
// Do database work here as normal
|
||||
//////////////////////////////////
|
||||
|
||||
// Once all database work is completed, stop the checkpoint
|
||||
// thread.
|
||||
CheckPointer.stopRunning();
|
||||
|
||||
// Join the checkpoint thread in case it needs some time to
|
||||
// cleanly shutdown.
|
||||
cp.join();
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("TryCheckPoint: " + e.toString());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
closeEnv();
|
||||
}
|
||||
System.out.println("All done.");
|
||||
}
|
||||
|
||||
// Open an environment and databases
|
||||
private static void openEnv() throws DatabaseException {
|
||||
System.out.println("opening env");
|
||||
|
||||
// Set up the environment.
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setAllowCreate(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
// EnvironmentConfig.setThreaded(true) is the default behavior
|
||||
// in Java, so we do not have to do anything to cause the
|
||||
// environment handle to be free-threaded.
|
||||
|
||||
try {
|
||||
// Open the environment
|
||||
myEnv = new Environment(new File(myEnvPath), // Env home
|
||||
myEnvConfig);
|
||||
|
||||
// Skipping the database opens and closes for brevity
|
||||
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
System.err.println("openEnv: " + fnfe.toString());
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the environment and databases
|
||||
private static void closeEnv() {
|
||||
System.out.println("Closing env");
|
||||
if (myEnv != null ) {
|
||||
try {
|
||||
myEnv.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TryCheckPoint() {}
|
||||
|
||||
private static void parseArgs(String args[]) {
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
if (args[i].startsWith("-")) {
|
||||
switch(args[i].charAt(1)) {
|
||||
case 'h':
|
||||
myEnvPath = new String(args[++i]);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="reversesplit.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="backuprestore.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Reverse BTree Splits </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Backup Procedures</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
41
docs/gsg_txn/JAVA/gettingStarted.css
Normal file
41
docs/gsg_txn/JAVA/gettingStarted.css
Normal file
@@ -0,0 +1,41 @@
|
||||
body { width: 45em;
|
||||
margin-left: 3em;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
h2.title { margin-left: -1em;
|
||||
font-family: Verdana, serif;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
h3.title { font-family: Verdana, serif;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
pre.programlisting {
|
||||
font-family: monospace;
|
||||
background-color: #eae8e9;
|
||||
}
|
||||
|
||||
div.navheader { font-size: 9pt;
|
||||
width: 60em;
|
||||
margin-left: -2em;
|
||||
}
|
||||
|
||||
div.navheader table tr td { font-size: 9pt; }
|
||||
|
||||
div.navfooter { font-size: 9pt;
|
||||
width: 60em;
|
||||
margin-left: -2em;
|
||||
}
|
||||
div.navfooter table tr td { font-size: 9pt; }
|
||||
|
||||
span.emphasis { font-style: italic; font-size: 9pt;}
|
||||
|
||||
div.appendix div.informaltable { font-size: 9pt; }
|
||||
div.appendix div.informaltable td { vertical-align: top; }
|
||||
div.appendix div.informaltable p { margin-top: .25em; }
|
||||
div.appendix div.informaltable p { margin-bottom: .25em; }
|
||||
|
||||
|
||||
210
docs/gsg_txn/JAVA/hotfailover.html
Normal file
210
docs/gsg_txn/JAVA/hotfailover.html
Normal file
@@ -0,0 +1,210 @@
|
||||
<?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>Using Hot Failovers</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="architectrecovery.html" title="Designing Your Application for Recovery" />
|
||||
<link rel="next" href="logfileremoval.html" title="Removing Log Files" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Using Hot Failovers</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="architectrecovery.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="logfileremoval.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="hotfailover"></a>Using Hot Failovers</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You can maintain a backup that can be used for failover purposes.
|
||||
Hot failovers differ from the backup and restore
|
||||
procedures described previously in this chapter in that data
|
||||
used for traditional backups is typically copied to offline storage.
|
||||
Recovery time for a traditional backup is determined by:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
How quickly you can retrieve that storage media.
|
||||
Typically storage media for critical backups is moved
|
||||
to a safe facility in a remote location, so this step can
|
||||
take a relatively long time.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
How fast you can read the backup from the storage media
|
||||
to a local disk drive. If you have very large backups,
|
||||
or if your storage media is very slow, this can be a
|
||||
lengthy process.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
How long it takes you to run catastrophic recovery
|
||||
against the newly restored backup. As described earlier
|
||||
in this chapter, this process can be lengthy because
|
||||
every log file must be examined during the recovery
|
||||
process.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
When you use a hot failover, the backup is maintained
|
||||
at a location that is reasonably fast to access. Usually, this
|
||||
is a second disk drive local to the machine.
|
||||
In this situation, recovery time is very quick
|
||||
because you only have to reopen your
|
||||
environment and database, using the failover environment
|
||||
for the environment open.
|
||||
</p>
|
||||
<p>
|
||||
Hot failovers obviously do not protect you from truly
|
||||
catastrophic disasters (such as a fire in your machine room)
|
||||
because the backup is still local to the machine. However,
|
||||
you can guard against more mundane problems (such as a broken
|
||||
disk drive) by keeping the backup on a
|
||||
second drive that is managed by an alternate disk controller.
|
||||
</p>
|
||||
<p>
|
||||
To maintain a hot failover:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Copy all the active database files to the failover
|
||||
directory. Use the <span><b class="command">db_archive</b></span>
|
||||
command line utility with the
|
||||
<tt class="literal">-s</tt> option to identify all the active
|
||||
database files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Identify all the inactive log files in your production
|
||||
environment and <span class="emphasis"><em>move</em></span> these to the failover
|
||||
directory. Use the <span><b class="command">db_archive</b></span>
|
||||
command with no command line options to obtain a list
|
||||
of these log files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Identify the active log files in your production
|
||||
environment, and <span class="emphasis"><em>copy</em></span> these to the
|
||||
failover directory. Use the
|
||||
<span><b class="command">db_archive</b></span> command with the
|
||||
<tt class="literal">-l</tt> option to obtain a list of these
|
||||
log files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Run catastrophic recovery against the failover
|
||||
directory. Use the <span><b class="command">db_recover</b></span>
|
||||
command with the <tt class="literal">-c</tt> option to do
|
||||
this.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Optionally copy the backup to an archival location.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
Once you have performed this procedure, you can maintain an
|
||||
active hot backup by repeating steps 2 - 5 as often
|
||||
as is required by your application.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
If you perform step 1, steps 2-5 must follow in order to
|
||||
ensure consistency of your hot backup.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Rather than use the previous procedure, you can use the <span><b class="command">db_hotbackup</b></span> command line utility
|
||||
to do the same thing. This utility will (optionally) run a checkpoint and then copy all necessary files to a target
|
||||
directory for you.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
To actually perform a failover, simply:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Shut down all processes which are running against the original environment.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you have an archival copy of the backup environment, you can optionally try copying the remaining
|
||||
log files from the original environment and running catastrophic recovery against that backup
|
||||
environment. Do this <span class="emphasis"><em>only</em></span> if you have a an archival copy of the backup
|
||||
environment.
|
||||
</p>
|
||||
<p>
|
||||
This step can allow you to recover data created or modified in the original environment, but which
|
||||
did not have a chance to be reflected in the hot backup environment.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Reopen your environment and databases as normal, but use
|
||||
the backup environment instead of the production
|
||||
environment.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="architectrecovery.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="logfileremoval.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Designing Your Application for Recovery </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Removing Log Files</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
583
docs/gsg_txn/JAVA/index.html
Normal file
583
docs/gsg_txn/JAVA/index.html
Normal file
@@ -0,0 +1,583 @@
|
||||
<?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>Getting Started with Berkeley DB Transaction Processing</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="next" href="preface.html" title="Preface" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Getting Started with Berkeley DB Transaction Processing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="book" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h1 class="title"><a id="id613728"></a>Getting Started with Berkeley DB Transaction Processing</h1>
|
||||
</div>
|
||||
<div>
|
||||
<div class="legalnotice">
|
||||
<p class="legalnotice-title">
|
||||
<b>Legal Notice</b>
|
||||
</p>
|
||||
<p>
|
||||
This documentation is distributed under an open source license.
|
||||
You may review the terms of this license at:
|
||||
<a href="http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html" target="_top">http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Oracle, Berkeley DB,
|
||||
|
||||
|
||||
and
|
||||
Sleepycat are trademarks or registered trademarks of
|
||||
Oracle. All rights to these marks are reserved.
|
||||
No third-party use is permitted without the
|
||||
express prior written consent of Oracle.
|
||||
</p>
|
||||
<p>
|
||||
<span class="trademark">Java</span>™ and all Java-based marks are a trademark
|
||||
or registered trademark of Sun Microsystems,
|
||||
Inc, in the United States and other countries.
|
||||
</p>
|
||||
<p>
|
||||
To obtain a copy of this document's original source code, please
|
||||
submit a request to the Oracle Technology Network forum at:
|
||||
<a href="http://forums.oracle.com/forums/forum.jspa?forumID=271" target="_top">http://forums.oracle.com/forums/forum.jspa?forumID=271</a>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="pubdate">4/25/2008</p>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="preface">
|
||||
<a href="preface.html">Preface</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="preface.html#conventions">Conventions Used in this Book</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="preface.html#moreinfo">For More Information</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="introduction.html">1. Introduction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="introduction.html#txnintro">Transaction Benefits</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#sysfailure">A Note on System Failure</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#apireq">Application Requirements</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#multithread-intro">Multi-threaded
|
||||
and Multi-process
|
||||
Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="recovery-intro.html">Recoverability</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="perftune-intro.html">Performance Tuning</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="enabletxn.html">2. Enabling Transactions</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="enabletxn.html#environments">Environments</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#filenaming">File Naming</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#errorsupport">Error Support</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#sharedmemory">Shared Memory Regions</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="enabletxn.html#security">Security Considerations</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="envopen.html">Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="usingtxns.html">3. Transaction Basics</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="usingtxns.html#commitresults">Committing a Transaction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="abortresults.html">Aborting a Transaction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="autocommit.html">Auto Commit</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="nestedtxn.html">Nested Transactions</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txncursor.html">Transactional Cursors</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txncursor.html#dplcursors">Using Transactional DPL Cursors</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnindices.html">Secondary Indices with Transaction Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="maxtxns.html">Configuring the Transaction Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="txnconcurrency.html">4. Concurrency</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnconcurrency.html#concurrenthandles">Which DB Handles are Free-Threaded</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="blocking_deadlocks.html">Locks, Blocks, and Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#locks">Locks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#blocks">Blocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#deadlocks">Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="lockingsubsystem.html">The Locking Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#configuringlock">Configuring the Locking Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#configdeadlkdetect">Configuring Deadlock Detection</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#deadlockresolve">Resolving Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="isolation.html">Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#degreesofisolation">Supported Degrees of Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#dirtyreads">Reading Uncommitted Data</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#readcommitted">Committed Reads</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txn_ccursor.html">Transactional Cursors and Concurrent Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txn_ccursor.html#cursordirtyreads">Using Cursors with Uncommitted Data</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="readmodifywrite.html">Read/Modify/Write</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnnowait.html">No Wait on Blocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="reversesplit.html">Reverse BTree Splits</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="filemanagement.html">5. Managing DB Files</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="filemanagement.html#checkpoints">Checkpoints</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="backuprestore.html">Backup Procedures</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#copyutilities">About Unix Copy Utilities</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#standardbackup">Offline Backups</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#hotbackup">Hot Backup</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="backuprestore.html#incrementalbackups">Incremental Backups</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="recovery.html">Recovery Procedures</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="recovery.html#normalrecovery">Normal Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="recovery.html#catastrophicrecovery">Catastrophic Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="architectrecovery.html">Designing Your Application for Recovery</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="architectrecovery.html#multithreadrecovery">Recovery for Multi-Threaded Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="architectrecovery.html#multiprocessrecovery">Recovery in Multi-Process Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="hotfailover.html">Using Hot Failovers</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="logfileremoval.html">Removing Log Files</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="logconfig.html">Configuring the Logging Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logfilesize">Setting the Log File Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logregionsize">Configuring the Logging Region Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="logconfig.html#logbuffer">Setting the In-Memory Log Buffer Size</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="chapter">
|
||||
<a href="wrapup.html">6. Summary and Examples</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="wrapup.html#anatomy">Anatomy of a Transactional Application</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnexample_java.html">Base API Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#txnguideexample">TxnGuide.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#payloaddata">PayloadData.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#dbwriter">DBWriter.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnexample_dpl.html">DPL Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#txnguideexample_dpl">TxnGuide.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#payloaddataentity">PayloadDataEntity.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#storewriter">StoreWriter.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="inmem_txnexample_java.html">Base API In-Memory Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"> </td>
|
||||
<td width="20%" align="center"> </td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top"> </td>
|
||||
<td width="20%" align="center"> </td>
|
||||
<td width="40%" align="right" valign="top"> Preface</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
561
docs/gsg_txn/JAVA/inmem_txnexample_java.html
Normal file
561
docs/gsg_txn/JAVA/inmem_txnexample_java.html
Normal file
@@ -0,0 +1,561 @@
|
||||
<?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>Base API In-Memory Transaction Example</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="wrapup.html" title="Chapter 6. Summary and Examples" />
|
||||
<link rel="previous" href="txnexample_dpl.html" title="DPL Transaction Example" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Base API In-Memory Transaction Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnexample_dpl.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 6. Summary and Examples</th>
|
||||
<td width="20%" align="right"> </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="inmem_txnexample_java"></a>Base API In-Memory Transaction Example</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB is sometimes used for applications that simply need to cache
|
||||
data retrieved from some other location (such as a remote database
|
||||
server). DB is also often used in embedded systems.
|
||||
</p>
|
||||
<p>
|
||||
In both cases, applications may still want to use transactions for
|
||||
atomicity, consistency, and isolation guarantees, but they may want
|
||||
to forgo the durability guarantee entirely. That is, they may want
|
||||
their DB environment and databases kept entirely in-memory so
|
||||
as to avoid the performance impact of unneeded disk I/O.
|
||||
</p>
|
||||
<p>
|
||||
To do this:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Refrain from specifying a home directory when you open your
|
||||
environment. The exception to this is if you are using the
|
||||
<tt class="literal">DB_CONFIG</tt> configuration file — in
|
||||
that case you must identify the environment's home
|
||||
directory so that the configuration file can be found.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Configure your environment to back your regions from
|
||||
system memory instead of the filesystem.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Configure your logging subsystem such that log files are kept
|
||||
entirely in-memory.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Increase the size of your in-memory log buffer so that it
|
||||
is large enough to hold the largest set of concurrent write operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Increase the size of your in-memory cache so that it can
|
||||
hold your entire data set. You do not want your cache to
|
||||
page to disk.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Do not specify a file name when you open your database(s).
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
As an example, this section takes the transaction example provided
|
||||
in <a href="txnexample_java.html">Base API Transaction Example</a>
|
||||
and it updates that example so that the environment, database, log
|
||||
files, and regions are all kept entirely in-memory.
|
||||
</p>
|
||||
<p>
|
||||
For illustration purposes, we also modify this example so that
|
||||
uncommitted reads are no longer used to enable the <tt class="methodname">countRecords()</tt>
|
||||
method. Instead, we simply provide a transaction handle to
|
||||
<tt class="methodname">countRecords()</tt> so as to avoid the
|
||||
self-deadlock.
|
||||
</p>
|
||||
<p>
|
||||
The majority of the modifications to the original example are performed in the <tt class="classname">TxnGuide</tt>
|
||||
example class (see <a href="txnexample_java.html#txnguideexample">TxnGuide.java</a>).
|
||||
This is because the majority of the work that we need to do is performed when the environment and
|
||||
databases are opened.
|
||||
</p>
|
||||
<p>
|
||||
To begin, we simplify the beginning of the class a bit. We eliminate some variables that the example no longer
|
||||
needs — specifically variables having to do with the location of the environment and the names of the
|
||||
database files.
|
||||
We can also remove our <tt class="function">usage()</tt> method because we no
|
||||
longer require any command line arguments.
|
||||
</p>
|
||||
<pre class="programlisting">// File TxnGuideInMemory.java
|
||||
|
||||
package db.txn;
|
||||
|
||||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.LockDetectMode;
|
||||
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
<b class="userinput"><tt>public class TxnGuideInMemory {</tt></b>
|
||||
|
||||
// DB handles
|
||||
private static Database myDb = null;
|
||||
private static Database myClassDb = null;
|
||||
private static Environment myEnv = null;
|
||||
|
||||
private static final int NUMTHREADS = 5; </pre>
|
||||
<p>
|
||||
Next, in our <tt class="function">main()</tt> method, we
|
||||
remove the call to <tt class="methodname">parseArgs()</tt> because that only existed in the previous example for
|
||||
collecting the environment home location. Everything else is essentially the same.
|
||||
</p>
|
||||
<pre class="programlisting"> public static void main(String args[]) {
|
||||
try {
|
||||
|
||||
// Open the environment and databases
|
||||
openEnv();
|
||||
|
||||
// Get our class catalog (used to serialize objects)
|
||||
StoredClassCatalog classCatalog =
|
||||
new StoredClassCatalog(myClassDb);
|
||||
|
||||
// Start the threads
|
||||
DBWriter[] threadArray;
|
||||
threadArray = new DBWriter[NUMTHREADS];
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i] = new DBWriter(myEnv, myDb, classCatalog);
|
||||
threadArray[i].start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i].join();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("<b class="userinput"><tt>TxnGuideInMemory</tt></b>: " + e.toString());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
closeEnv();
|
||||
}
|
||||
System.out.println("All done.");
|
||||
} </pre>
|
||||
<p>
|
||||
Next we open our environment as always. However, in doing so we:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Set <tt class="methodname">EnvironmentConfig.setPrivate()</tt>
|
||||
to <tt class="literal">true</tt>.
|
||||
This causes our environment to back regions using our
|
||||
application's heap memory rather than by using the filesystem.
|
||||
This is the first important step to keeping our DB data
|
||||
entirely in-memory.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Remove <tt class="methodname">runRecovery()</tt>
|
||||
from the environment configuration. Because all our data will be held entirely in memory, recovery is a
|
||||
non-issue. Note that if we had left the call to <tt class="methodname">runRecovery()</tt>
|
||||
in, it would be silently ignored.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<pre class="programlisting"> private static void openEnv() throws DatabaseException {
|
||||
System.out.println("opening env");
|
||||
|
||||
// Set up the environment.
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
|
||||
<b class="userinput"><tt>// Region files are not backed by the filesystem, they are
|
||||
// backed by heap memory.
|
||||
myEnvConfig.setPrivate(true);</tt></b>
|
||||
|
||||
myEnvConfig.setAllowCreate(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
// EnvironmentConfig.setThreaded(true) is the default behavior
|
||||
// in Java, so we do not have to do anything to cause the
|
||||
// environment handle to be free-threaded.
|
||||
|
||||
// Indicate that we want db to internally perform deadlock
|
||||
// detection. Also indicate that the transaction that has
|
||||
// performed the least amount of write activity to
|
||||
// receive the deadlock notification, if any.
|
||||
myEnvConfig.setLockDetectMode(LockDetectMode.MINWRITE); </pre>
|
||||
<p>
|
||||
Now we configure our environment to keep the log files in memory,
|
||||
increase the log buffer size to 10 MB, and increase our in-memory
|
||||
cache to 10 MB. These values should be more than enough for our
|
||||
application's workload.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<b class="userinput">
|
||||
<tt> // Specify in-memory logging
|
||||
myEnvConfig.setLogInMemory(true);
|
||||
// Specify the size of the in-memory log buffer
|
||||
// Must be large enough to handle the log data created by
|
||||
// the largest transaction.
|
||||
myEnvConfig.setLogBufferSize(10 * 1024 * 1024);
|
||||
// Specify the size of the in-memory cache
|
||||
// Set it large enough so that it won't page.
|
||||
myEnvConfig.setCacheSize(10 * 1024 * 1024); </tt>
|
||||
</b>
|
||||
</pre>
|
||||
<p>
|
||||
Our database configuration is identical to the original example, except that we do not specify
|
||||
<tt class="methodname">setReadUncomitted()</tt> here. We will be causing our <tt class="methodname">countRecords()</tt>
|
||||
method to join the transaction rather than perform uncommitted reads, so we do not need our database to support them.
|
||||
</p>
|
||||
<pre class="programlisting"> // Set up the database
|
||||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||||
myDbConfig.setType(DatabaseType.BTREE);
|
||||
myDbConfig.setAllowCreate(true);
|
||||
myDbConfig.setTransactional(true);
|
||||
myDbConfig.setSortedDuplicates(true);
|
||||
// no DatabaseConfig.setThreaded() method available.
|
||||
// db handles in java are free-threaded so long as the
|
||||
// env is also free-threaded. </pre>
|
||||
<p>
|
||||
Next, we open the environment. This is
|
||||
identical to how the example previously worked, except that we do not
|
||||
provide a location for the environment's home directory.
|
||||
</p>
|
||||
<pre class="programlisting"> try {
|
||||
// Open the environment
|
||||
myEnv = new Environment(<b class="userinput"><tt>null</tt></b>, // Env home
|
||||
myEnvConfig); </pre>
|
||||
<p>
|
||||
When we open our databases, we also specify <tt class="literal">null</tt> for the file names. The causes the database
|
||||
to not be backed by the filesystem; that is, the databases are held entirely in memory.
|
||||
</p>
|
||||
<pre class="programlisting"> // Open the database. Do not provide a txn handle. This open
|
||||
// is auto committed because DatabaseConfig.setTransactional()
|
||||
// is true.
|
||||
myDb = myEnv.openDatabase(null, // txn handle
|
||||
<b class="userinput"><tt>null</tt></b>, // Database file name
|
||||
null, // Database name
|
||||
myDbConfig);
|
||||
|
||||
// Used by the bind API for serializing objects
|
||||
// Class database must not support duplicates
|
||||
myDbConfig.setSortedDuplicates(false);
|
||||
myClassDb = myEnv.openDatabase(null, // txn handle
|
||||
<b class="userinput"><tt>null</tt></b>, // Database file name
|
||||
null, // Database name,
|
||||
myDbConfig);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
System.err.println("openEnv: " + fnfe.toString());
|
||||
System.exit(-1);
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
After that, our class is unchanged, except for some very minor modifications.
|
||||
Most notably, we remove the <tt class="methodname">parseArgs()</tt>
|
||||
method from the application, because we no longer need it.
|
||||
</p>
|
||||
<pre class="programlisting"> private static void closeEnv() {
|
||||
System.out.println("Closing env");
|
||||
if (myDb != null ) {
|
||||
try {
|
||||
myDb.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: myDb: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (myClassDb != null ) {
|
||||
try {
|
||||
myClassDb.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: myClassDb: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (myEnv != null ) {
|
||||
try {
|
||||
myEnv.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<b class="userinput"><tt>private TxnGuideInMemory() {}</tt></b>
|
||||
} </pre>
|
||||
<p>
|
||||
That completes our modifications to this class.
|
||||
We now turn our attention to our <tt class="classname">DBWriter</tt>
|
||||
class (see <a href="txnexample_java.html#dbwriter">DBWriter.java</a>).
|
||||
It is unchanged, except for one small modification. In the
|
||||
<tt class="methodname">run()</tt> method, we call <tt class="methodname">countRecords()</tt>
|
||||
with a transaction handle, rather than configuring our entire
|
||||
application for uncommitted reads. Both mechanisms work well-enough
|
||||
for preventing a self-deadlock. However, the individual count
|
||||
in this example will tend to be lower than the counts seen in
|
||||
the previous transaction example, because
|
||||
<tt class="function">countRecords()</tt> can no longer see records
|
||||
created but not yet committed by other threads.
|
||||
Additionally, the usage of the transaction handle here will
|
||||
probably cause more deadlocks than using read-uncommitted does, because more locking is being performed in
|
||||
this case.
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.bind.EntryBinding;
|
||||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||||
import com.sleepycat.bind.serial.SerialBinding;
|
||||
import com.sleepycat.bind.tuple.StringBinding;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.CursorConfig;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DeadlockException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Random;
|
||||
|
||||
public class DBWriter extends Thread
|
||||
{
|
||||
private Database myDb = null;
|
||||
private Environment myEnv = null;
|
||||
private EntryBinding dataBinding = null;
|
||||
private Random generator = new Random();
|
||||
|
||||
private static final int MAX_RETRY = 20;
|
||||
|
||||
private static String[] keys = {"key 1", "key 2", "key 3",
|
||||
"key 4", "key 5", "key 6",
|
||||
"key 7", "key 8", "key 9",
|
||||
"key 10"};
|
||||
|
||||
|
||||
// Constructor. Get our DB handles from here
|
||||
DBWriter(Environment env, Database db, StoredClassCatalog scc)
|
||||
throws DatabaseException {
|
||||
myDb = db;
|
||||
myEnv = env;
|
||||
dataBinding = new SerialBinding(scc, PayloadData.class);
|
||||
}
|
||||
|
||||
|
||||
// Thread method that writes a series of records
|
||||
// to the database using transaction protection.
|
||||
// Deadlock handling is demonstrated here.
|
||||
public void run () {
|
||||
Transaction txn = null;
|
||||
|
||||
// Perform 50 transactions
|
||||
for (int i=0; i<50; i++) {
|
||||
|
||||
boolean retry = true;
|
||||
int retry_count = 0;
|
||||
// while loop is used for deadlock retries
|
||||
while (retry) {
|
||||
// try block used for deadlock detection and
|
||||
// general db exception handling
|
||||
try {
|
||||
|
||||
// Get a transaction
|
||||
txn = myEnv.beginTransaction(null, null);
|
||||
// Write 10 records to the db
|
||||
// for each transaction
|
||||
for (int j = 0; j < 10; j++) {
|
||||
// Get the key
|
||||
DatabaseEntry key = new DatabaseEntry();
|
||||
StringBinding.stringToEntry(keys[j], key);
|
||||
|
||||
// Get the data
|
||||
PayloadData pd = new PayloadData(i+j, getName(),
|
||||
generator.nextDouble());
|
||||
DatabaseEntry data = new DatabaseEntry();
|
||||
dataBinding.objectToEntry(pd, data);
|
||||
|
||||
// Do the put
|
||||
myDb.put(txn, key, data);
|
||||
}
|
||||
|
||||
// commit
|
||||
System.out.println(getName() +
|
||||
" : committing txn : " + i);
|
||||
|
||||
System.out.println(getName() + " : Found " +
|
||||
countRecords(<b class="userinput"><tt>txn</tt></b>) + " records in the database.");
|
||||
try {
|
||||
txn.commit();
|
||||
txn = null;
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("Error on txn commit: " +
|
||||
e.toString());
|
||||
}
|
||||
retry = false;
|
||||
|
||||
} catch (DeadlockException de) {
|
||||
System.out.println("################# " + getName() +
|
||||
" : caught deadlock");
|
||||
// retry if necessary
|
||||
if (retry_count < MAX_RETRY) {
|
||||
System.err.println(getName() +
|
||||
" : Retrying operation.");
|
||||
retry = true;
|
||||
retry_count++;
|
||||
} else {
|
||||
System.err.println(getName() +
|
||||
" : out of retries. Giving up.");
|
||||
retry = false;
|
||||
}
|
||||
} catch (DatabaseException e) {
|
||||
// abort and don't retry
|
||||
retry = false;
|
||||
System.err.println(getName() +
|
||||
" : caught exception: " + e.toString());
|
||||
System.err.println(getName() +
|
||||
" : errno: " + e.getErrno());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (txn != null) {
|
||||
try {
|
||||
txn.abort();
|
||||
} catch (Exception e) {
|
||||
System.err.println(
|
||||
"Error aborting transaction: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Next we update <tt class="methodname">countRecords()</tt>. The only difference
|
||||
here is that we no longer specify <tt class="methodname">CursorConfig.setReadUncomitted()</tt> when
|
||||
we open our cursor. Note that even this minor change is not required.
|
||||
If we do not configure our database to support uncommitted reads,
|
||||
<tt class="methodname">CursorConfig.setReadUncomitted()</tt> is silently
|
||||
ignored. However, we remove the property anyway from the cursor open so as to
|
||||
avoid confusion.
|
||||
</p>
|
||||
<pre class="programlisting"> // This simply counts the number of records contained in the
|
||||
// database and returns the result. You can use this method
|
||||
// in three ways:
|
||||
//
|
||||
// First call it with an active txn handle.
|
||||
// Secondly, configure the cursor for uncommitted reads
|
||||
// Third, call count_records AFTER the writer has committed
|
||||
// its transaction.
|
||||
//
|
||||
// If you do none of these things, the writer thread will
|
||||
// self-deadlock.
|
||||
//
|
||||
// Note that this method exists only for illustrative purposes.
|
||||
// A more straight-forward way to count the number of records in
|
||||
// a database is to use the Database.getStats() method.
|
||||
private int countRecords(Transaction txn) throws DatabaseException {
|
||||
DatabaseEntry key = new DatabaseEntry();
|
||||
DatabaseEntry data = new DatabaseEntry();
|
||||
int count = 0;
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
// Get the cursor
|
||||
CursorConfig cc = new CursorConfig();
|
||||
cc.setReadUncomitted(true);
|
||||
cursor = myDb.openCursor(txn, cc);
|
||||
while (cursor.getNext(key, data, LockMode.DEFAULT) ==
|
||||
OperationStatus.SUCCESS) {
|
||||
|
||||
count++;
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
This completes our in-memory transactional example. If you would like to
|
||||
experiment with this code, you can find the example in the following
|
||||
location in your DB distribution:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_java/src/db/txn</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnexample_dpl.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="wrapup.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">DPL Transaction Example </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
486
docs/gsg_txn/JAVA/introduction.html
Normal file
486
docs/gsg_txn/JAVA/introduction.html
Normal file
@@ -0,0 +1,486 @@
|
||||
<?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>Chapter 1. Introduction</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="preface.html" title="Preface" />
|
||||
<link rel="next" href="recovery-intro.html" title="Recoverability" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 1. Introduction</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="recovery-intro.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="introduction"></a>Chapter 1. Introduction</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="introduction.html#txnintro">Transaction Benefits</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#sysfailure">A Note on System Failure</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#apireq">Application Requirements</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="introduction.html#multithread-intro">Multi-threaded
|
||||
and Multi-process
|
||||
Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="recovery-intro.html">Recoverability</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="perftune-intro.html">Performance Tuning</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
This book provides a thorough introduction and discussion on transactions as
|
||||
used with Berkeley DB (DB). <span>Both the
|
||||
base API as well as the Direct Persistence Layer API is used in this
|
||||
manual.</span> It begins by offering a general overview to
|
||||
transactions, the guarantees they provide, and the general application
|
||||
infrastructure required to obtain full transactional protection for your
|
||||
data.
|
||||
</p>
|
||||
<p>
|
||||
This book also provides detailed examples on how to write a
|
||||
transactional application. Both single threaded and multi-threaded <span>(as well as multi-process
|
||||
applications)</span> are discussed. A detailed description of various
|
||||
backup and recovery strategies is included in this manual, as is a
|
||||
discussion on performance considerations for your transactional application.
|
||||
</p>
|
||||
<p>
|
||||
You should understand the concepts from the
|
||||
<span>
|
||||
<i class="citetitle">Getting Started with Berkeley DB</i>
|
||||
</span>
|
||||
|
||||
|
||||
guide before reading this book.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="txnintro"></a>Transaction Benefits</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Transactions offer your application's data protection from
|
||||
application or system failures. That is, DB transactions offer
|
||||
your application full ACID support:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<span class="bold"><b>A</b></span>tomicity
|
||||
</p>
|
||||
<p>
|
||||
Multiple database operations are treated as a single unit of
|
||||
work. Once committed, all write operations performed under
|
||||
the protection of the transaction are saved to your databases.
|
||||
Further, in the event that you abort a transaction, all write
|
||||
operations performed during the transaction are discarded.
|
||||
In this event, your database is left in the state it was in
|
||||
before the transaction began, regardless of the number or
|
||||
type of write operations you may have performed during the
|
||||
course of the transaction.
|
||||
</p>
|
||||
<p>
|
||||
Note that DB transactions can span one or more
|
||||
database handles.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="bold"><b>C</b></span>onsistency
|
||||
</p>
|
||||
<p>
|
||||
Your databases will never see a partially completed
|
||||
transaction. This is true even if your application fails while there are
|
||||
in-progress transactions. If the application or system fails,
|
||||
then either all of the database changes appear when the
|
||||
application next runs, or none of them appear.
|
||||
</p>
|
||||
<p>
|
||||
In other words, whatever consistency requirements your application has will never be violated by DB.
|
||||
If, for example, your application requires every record to include an employee ID, and your
|
||||
code faithfully adds that ID to its database records, then DB will never
|
||||
violate that consistency requirement. The ID will remain in the database records until such a time as your
|
||||
application chooses to delete it.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="bold"><b>I</b></span>solation
|
||||
</p>
|
||||
<p>
|
||||
While a transaction is in progress, your databases will appear
|
||||
to the transaction as if there are no other operations
|
||||
occurring outside of the transaction. That is, operations
|
||||
wrapped inside a transaction will always have a clean and
|
||||
consistent view of your databases. They never have to see
|
||||
updates currently in progress under the protection of another transaction.
|
||||
Note, however, that isolation guarantees can be
|
||||
|
||||
relaxed from the default setting. See
|
||||
<a href="isolation.html">Isolation</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="bold"><b>D</b></span>urability
|
||||
</p>
|
||||
<p>
|
||||
Once committed to your databases, your modifications will
|
||||
persist even in the event of an application or system failure.
|
||||
Note that like isolation, your durability guarantee can be
|
||||
relaxed. See <a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="sysfailure"></a>A Note on System Failure</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
From time to time this manual mentions that transactions protect your data against 'system or application
|
||||
failure.' This is
|
||||
true up to a certain extent. However, not all failures are created equal and no data protection
|
||||
mechanism can protect you against every conceivable way a computing system can find to die.
|
||||
</p>
|
||||
<p>
|
||||
Generally, when this book talks about protection against failures, it means that
|
||||
transactions offer protection against
|
||||
the likeliest culprits for system and application crashes. So long as your data modifications have been
|
||||
committed to disk, those modifications should persist even if your application or OS subsequently fails.
|
||||
And, even if the application or OS fails in the middle of a transaction commit (or abort), the data on disk
|
||||
should be either in a consistent state, or there should be enough data available to bring
|
||||
your databases into a consistent state (via a recovery procedure, for example). You may, however,
|
||||
lose whatever data you were committing at the
|
||||
time of the failure, but your databases will be otherwise unaffected.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Be aware that many disks have a disk write cache and on
|
||||
some systems it is enabled by default. This means that
|
||||
a transaction can have committed, and to your
|
||||
application the data may appear to reside on disk, but
|
||||
the data may in fact reside only in the write cache at
|
||||
that time. This means that if the disk write cache is
|
||||
enabled and there is no battery backup for it, data can
|
||||
be lost after an OS crash even when maximum durability
|
||||
mode is in use. For maximum durability, disable the
|
||||
disk write cache or use a disk write cache with a
|
||||
battery backup.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Of course, if your <span class="emphasis"><em>disk</em></span> fails, then the transactional benefits described in this book
|
||||
are only as good as the backups you have taken.
|
||||
|
||||
|
||||
<span>
|
||||
By spreading your data and log files across separate disks,
|
||||
you can minimize the risk of data loss due to a disk failure, but even in this case it is possible to
|
||||
conjure a scenario where even this protection is insufficient (a fire in the machine room, for example) and
|
||||
you must go to your backups for protection.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Finally, by following the programming examples shown in this book, you can write your code so as to protect
|
||||
your data in the event that your code crashes. However, no programming API can protect you against logic
|
||||
failures in your own code; transactions cannot protect you from simply writing the wrong thing to your
|
||||
databases.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="apireq"></a>Application Requirements</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to use transactions, your application has certain
|
||||
requirements beyond what is required of non-transactional protected
|
||||
applications. They are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Environments.
|
||||
</p>
|
||||
<p>
|
||||
Environments are optional for non-transactional
|
||||
applications, but they are required for transactional
|
||||
applications.
|
||||
</p>
|
||||
<p>
|
||||
Environments are optional for non-transactional
|
||||
applications that use the base API, but they are required for transactional
|
||||
applications. (Of course, applications that use the
|
||||
DPL always require the DPL.)
|
||||
</p>
|
||||
<p>
|
||||
Environment usage is described in detail in
|
||||
<a href="usingtxns.html">Transaction Basics</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Transaction subsystem.
|
||||
</p>
|
||||
<p>
|
||||
In order to use transactions, you must explicitly
|
||||
enable the transactional subsystem for your
|
||||
application, and this must be done at the time that
|
||||
your environment is first created.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Logging subsystem.
|
||||
</p>
|
||||
<p>
|
||||
The logging subsystem is required for recovery purposes, but
|
||||
its usage also means your application may require a
|
||||
little more administrative effort than it does when logging
|
||||
is not in use. See <a href="filemanagement.html">Managing DB Files</a> for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<span>Transaction</span>
|
||||
|
||||
handles.
|
||||
</p>
|
||||
<p>
|
||||
In order to obtain the atomicity guarantee offered by
|
||||
the transactional subsystem (that is, combine multiple
|
||||
operations in a single unit of work), your application must use
|
||||
transaction handles. These handles are obtained from your
|
||||
|
||||
|
||||
|
||||
<span>Environment</span>
|
||||
objects. They should normally be short-lived, and their usage is
|
||||
reasonably simple. To complete a transaction and save
|
||||
the work it performed, you
|
||||
call its <tt class="methodname">commit()</tt> method. To
|
||||
complete a transaction and discard its work, you call its
|
||||
<tt class="methodname">abort()</tt> method.
|
||||
</p>
|
||||
<p>
|
||||
In addition, it is possible to use auto commit if you want
|
||||
to transactional protect a single write operation. Auto
|
||||
commit allows a transaction to be used without
|
||||
obtaining an explicit transaction handle. See
|
||||
<a href="autocommit.html">Auto Commit</a>
|
||||
for information on how to use auto commit.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Entity Store
|
||||
</p>
|
||||
<p>
|
||||
If you are using the DPL, then you must
|
||||
configure your entity stores for transactional
|
||||
support before opening them (that is, before
|
||||
obtaining a primary key from them for the first
|
||||
time).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span>Database</span>
|
||||
|
||||
open requirements.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
<span>In addition to using
|
||||
environments and initializing the
|
||||
correct subsystems, your</span>
|
||||
|
||||
application must transaction protect the database
|
||||
|
||||
opens<span>,
|
||||
and any secondary index associations,</span>
|
||||
|
||||
if subsequent operations on the databases are to be transaction
|
||||
protected. The database open and secondary index
|
||||
association are commonly transaction protected using
|
||||
auto commit.
|
||||
</p>
|
||||
<p>
|
||||
Note that if you are using the DPL, you do not
|
||||
have to explicitly do anything to the underlying
|
||||
databases unless you want to modify their default
|
||||
behavior — such as the isolation level that they
|
||||
use, for example.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Deadlock detection.
|
||||
</p>
|
||||
<p>
|
||||
Typically transactional applications use multiple
|
||||
threads of control when accessing the database. Any
|
||||
time multiple threads are used on a single resource,
|
||||
the potential for lock contention arises. In turn, lock
|
||||
contention can lead to deadlocks. See
|
||||
<a href="blocking_deadlocks.html">Locks, Blocks, and Deadlocks</a>
|
||||
for more information.
|
||||
</p>
|
||||
<p>
|
||||
Therefore, transactional applications must frequently
|
||||
include code for detecting and responding to deadlocks.
|
||||
Note that this requirement is not
|
||||
<span class="emphasis"><em>specific</em></span> to transactions
|
||||
– you can certainly write concurrent
|
||||
non-transactional DB applications. Further, not
|
||||
every transactional application uses concurrency and
|
||||
so not every transactional application must
|
||||
manage deadlocks. Still, deadlock management is so
|
||||
frequently a characteristic of transactional
|
||||
applications that we discuss it in this
|
||||
book. See <a href="txnconcurrency.html">Concurrency</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="multithread-intro"></a>Multi-threaded
|
||||
<span>and Multi-process</span>
|
||||
Applications</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB is designed to support multi-threaded <span>and
|
||||
multi-process</span> applications, but their usage means
|
||||
you must pay careful attention to issues of concurrency.
|
||||
Transactions help your application's concurrency by providing various levels of
|
||||
isolation for your threads of control. In addition, DB
|
||||
provides mechanisms that allow you to detect and respond to
|
||||
deadlocks (but strictly speaking, this is not limited to just
|
||||
transactional applications).
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em>Isolation</em></span> means that database modifications made by
|
||||
one transaction will not normally be seen by readers from another
|
||||
transaction until the first commits its changes. Different threads
|
||||
use different transaction handles, so
|
||||
this mechanism is normally used to provide isolation between
|
||||
database operations performed by different threads.
|
||||
</p>
|
||||
<p>
|
||||
Note that DB supports different isolation levels. For example,
|
||||
you can configure your application to see uncommitted reads, which means
|
||||
that one transaction can see data that has been modified but not yet
|
||||
committed by another transaction. Doing this might mean your
|
||||
transaction reads data "dirtied" by another transaction,
|
||||
but which subsequently might change before that
|
||||
other transaction commits its changes.
|
||||
On the other hand, lowering your isolation
|
||||
requirements means that your application can experience
|
||||
improved throughput due to reduced lock contention.
|
||||
</p>
|
||||
<p>
|
||||
For more information on concurrency, on managing isolation
|
||||
levels, and on deadlock detection, see <a href="txnconcurrency.html">Concurrency</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="recovery-intro.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Preface </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Recoverability</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1042
docs/gsg_txn/JAVA/isolation.html
Normal file
1042
docs/gsg_txn/JAVA/isolation.html
Normal file
File diff suppressed because it is too large
Load Diff
479
docs/gsg_txn/JAVA/lockingsubsystem.html
Normal file
479
docs/gsg_txn/JAVA/lockingsubsystem.html
Normal file
@@ -0,0 +1,479 @@
|
||||
<?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>The Locking Subsystem</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="blocking_deadlocks.html" title="Locks, Blocks, and Deadlocks" />
|
||||
<link rel="next" href="isolation.html" title="Isolation" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">The Locking Subsystem</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Concurrency</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="isolation.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="lockingsubsystem"></a>The Locking Subsystem</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to allow concurrent operations, DB provides the locking
|
||||
subsystem. This subsystem provides inter- and intra- process
|
||||
concurrency mechanisms. It is extensively used by DB concurrent
|
||||
applications, but it can also be generally used for non-DB
|
||||
resources.
|
||||
</p>
|
||||
<p>
|
||||
This section describes the locking subsystem as it is used to
|
||||
protect DB resources. In particular, issues on configuration are
|
||||
examined here. For information on using the locking subsystem to
|
||||
manage non-DB resources, see the
|
||||
<i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="configuringlock"></a>Configuring the Locking Subsystem</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You initialize the locking subsystem by specifying
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setInitializeLocking()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Before opening your environment, you can configure various
|
||||
maximum values for your locking subsystem. Note that these
|
||||
limits can only be configured before the environment is
|
||||
opened. Also, these methods configure the entire environment,
|
||||
not just a specific environment handle.
|
||||
</p>
|
||||
<p>
|
||||
Finally, each bullet below identifies the
|
||||
<tt class="filename">DB_CONFIG</tt> file parameter that can be used
|
||||
to specify the specific locking limit. If used, these
|
||||
<tt class="filename">DB_CONFIG</tt> file parameters override any
|
||||
value that you might specify using the environment handle.
|
||||
</p>
|
||||
<p>
|
||||
The limits that you can configure are as follows:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
The maximum number of lockers
|
||||
supported by the environment. This value is used by
|
||||
the environment when it is opened to estimate the amount
|
||||
of space that it should allocate for various internal
|
||||
data structures. By default, 1,000 lockers are
|
||||
supported.
|
||||
</p>
|
||||
<p>
|
||||
To configure this value, use the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setMaxLockers()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
As an alternative to this method, you can configure this
|
||||
value using the <tt class="filename">DB_CONFIG</tt> file's
|
||||
<tt class="literal">set_lk_max_lockers</tt> parameter.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The maximum number of locks supported by the environment.
|
||||
By default, 1,000 locks are supported.
|
||||
</p>
|
||||
<p>
|
||||
To configure this value, use the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setMaxLocks()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
As an alternative to this method, you can configure this
|
||||
value using the <tt class="filename">DB_CONFIG</tt> file's
|
||||
<tt class="literal">set_lk_max_locks</tt> parameter.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The maximum number of locked objects supported by the environment.
|
||||
By default, 1,000 objects can be locked.
|
||||
</p>
|
||||
<p>
|
||||
To configure this value, use the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setMaxLockObjects()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
As an alternative to this method, you can configure this
|
||||
value using the <tt class="filename">DB_CONFIG</tt> file's
|
||||
<tt class="literal">set_lk_max_objects</tt> parameter.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For a definition of lockers, locks, and locked objects, see
|
||||
<a href="blocking_deadlocks.html#lockresources">Lock Resources</a>.
|
||||
</p>
|
||||
<p>
|
||||
For example, to configure the maximum number of locks that your
|
||||
environment can use:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setTransactional(true);
|
||||
myEnvConfig.setMaxLocks(5000);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="configdeadlkdetect"></a>Configuring Deadlock Detection</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order for DB to know that a deadlock has occurred,
|
||||
some mechanism must be used to perform deadlock
|
||||
detection. There are three ways that deadlock detection can
|
||||
occur:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Allow DB to internally detect deadlocks as they
|
||||
occur.
|
||||
</p>
|
||||
<p>
|
||||
To do this, you use
|
||||
|
||||
|
||||
<span><tt class="methodname">EnvironmentConfig.setLockDetectMode()</tt>.</span>
|
||||
This method causes DB to walk its internal lock table
|
||||
looking for a deadlock whenever a lock request
|
||||
is blocked. This method also identifies how DB decides which lock
|
||||
requests are rejected when deadlocks are detected. For example,
|
||||
DB can decide to reject the lock request for the transaction
|
||||
that has the most number of locks, the least number of locks,
|
||||
holds the oldest lock, holds the most number of write locks, and
|
||||
so forth (see the API reference documentation for a complete
|
||||
list of the lock detection policies).
|
||||
</p>
|
||||
<p>
|
||||
You can call this method at any time during your application's
|
||||
lifetime, but typically it is used before you open your environment.
|
||||
</p>
|
||||
<p>
|
||||
Note that how you want DB to decide which thread of control should break a deadlock is
|
||||
extremely dependent on the nature of your application. It is not unusual for some performance
|
||||
testing to be required in order to make this determination. That said, a transaction that is
|
||||
holding the maximum number of locks is usually indicative of the transaction that has performed
|
||||
the most amount of work. Frequently you will not want a transaction that has performed a lot of
|
||||
work to abandon its efforts and start all over again. It is not therefore uncommon for
|
||||
application developers to initially select the transaction with the <span class="emphasis"><em>minimum</em></span>
|
||||
number of write locks to break the deadlock.
|
||||
</p>
|
||||
<p>
|
||||
Using this mechanism for deadlock detection means
|
||||
that your application will never have to wait on a
|
||||
lock before discovering that a deadlock has
|
||||
occurred. However, walking the lock table every
|
||||
time a lock request is blocked can be expensive
|
||||
from a performance perspective.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Use a dedicated thread or external process to perform
|
||||
deadlock detection. Note that this thread must be
|
||||
performing no other database operations beyond deadlock
|
||||
detection.
|
||||
</p>
|
||||
<p>
|
||||
To externally perform lock detection, you can use
|
||||
either the
|
||||
|
||||
|
||||
<tt class="methodname">Environment.detectDeadlocks()</tt>
|
||||
method, or use the
|
||||
<span><b class="command">db_deadlock</b></span> command line
|
||||
utility. This method (or command) causes DB to walk the
|
||||
lock table looking for deadlocks.
|
||||
</p>
|
||||
<p>
|
||||
Note that like
|
||||
|
||||
|
||||
<span><tt class="methodname">EnvironmentConfig.setLockDetectMode()</tt>,</span>
|
||||
you also use this method (or command line utility)
|
||||
to identify which lock requests are rejected in the
|
||||
event that a deadlock is detected.
|
||||
</p>
|
||||
<p>
|
||||
Applications that perform deadlock detection in
|
||||
this way typically run deadlock detection between every few
|
||||
seconds and a minute. This means that your
|
||||
application may have to wait to be notified of a
|
||||
deadlock, but you also save the overhead of walking
|
||||
the lock table every time a lock request is blocked.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Lock timeouts.
|
||||
</p>
|
||||
<p>
|
||||
You can configure your locking subsystem such that
|
||||
it times out any lock that is not released within a
|
||||
specified amount of time. To do this, use the
|
||||
|
||||
|
||||
<span><tt class="methodname">EnvironmentConfig.setLockTimeout()</tt></span>
|
||||
method.
|
||||
Note that lock timeouts are only checked when a
|
||||
lock request is blocked or when deadlock
|
||||
detection is otherwise performed. Therefore, a lock can have timed out and still be held for
|
||||
some length of time until DB has a reason to examine its locking tables.
|
||||
</p>
|
||||
<p>
|
||||
Be aware that extremely long-lived transactions, or
|
||||
operations that hold locks for a long time, may be
|
||||
inappropriately timed out before the transaction or
|
||||
operation has a chance to complete. You should
|
||||
therefore use this mechanism only if you know your
|
||||
application will hold locks for very short periods
|
||||
of time.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
For example, to configure your application such that DB
|
||||
checks the lock table for deadlocks every time a lock
|
||||
request is blocked:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.LockDetectMode;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setTransactional(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
|
||||
// Configure db to perform deadlock detection internally, and to
|
||||
// choose the transaction that has performed the least amount
|
||||
// of writing to break the deadlock in the event that one
|
||||
// is detected.
|
||||
envConfig.setLockDetectMode(LockDetectMode.MINWRITE);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// From here, you open your databases, proceed with your
|
||||
// database operations, and respond to deadlocks as
|
||||
// is normal (omitted for brevity).
|
||||
|
||||
...</pre>
|
||||
<p>
|
||||
Finally, the following command line call causes
|
||||
deadlock detection to be run against the
|
||||
environment contained in <tt class="literal">/export/dbenv</tt>. The
|
||||
transaction with the youngest lock is chosen to break the
|
||||
deadlock:
|
||||
</p>
|
||||
<pre class="programlisting">> /usr/local/db_install/bin/db_deadlock -h /export/dbenv -a y</pre>
|
||||
<p>
|
||||
For more information, see the
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_deadlock.html" target="_top">
|
||||
<tt class="literal">db_deadlock</tt> reference documentation.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="deadlockresolve"></a>Resolving Deadlocks</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When DB determines that a deadlock has occurred, it will
|
||||
select a thread of control to resolve the deadlock and then
|
||||
|
||||
|
||||
<span>
|
||||
throws <tt class="literal">DeadlockException</tt> in that
|
||||
thread.
|
||||
</span>
|
||||
|
||||
If a deadlock is detected, the thread must:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Cease all read and write operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Close all open cursors.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Abort the transaction.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Optionally retry the operation. If your application
|
||||
retries deadlocked operations, the new attempt must
|
||||
be made using a new transaction.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
If a thread has deadlocked, it may not make any
|
||||
additional database calls using the handle that has
|
||||
deadlocked.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">// retry_count is a counter used to identify how many times
|
||||
// we've retried this operation. To avoid the potential for
|
||||
// endless looping, we won't retry more than MAX_DEADLOCK_RETRIES
|
||||
// times.
|
||||
|
||||
// txn is a transaction handle.
|
||||
// key and data are DatabaseEntry handles. Their usage is not shown here.
|
||||
while (retry_count < MAX_DEADLOCK_RETRIES) {
|
||||
try {
|
||||
txn = myEnv.beginTransaction(null, null);
|
||||
myDatabase.put(txn, key, data);
|
||||
txn.commit();
|
||||
return 0;
|
||||
} catch (DeadlockException de) {
|
||||
try {
|
||||
// Abort the transaction and increment the
|
||||
// retry counter
|
||||
txn.abort();
|
||||
retry_count++;
|
||||
if (retry_count >= MAX_DEADLOCK_RETRIES) {
|
||||
System.err.println("Exceeded retry limit. Giving up.");
|
||||
return -1;
|
||||
}
|
||||
} catch (DatabaseException ae) {
|
||||
System.err.println("txn abort failed: " + ae.toString());
|
||||
return -1;
|
||||
}
|
||||
} catch (DatabaseException e) {
|
||||
try {
|
||||
// Abort the transaction.
|
||||
txn.abort();
|
||||
} catch (DatabaseException ae) {
|
||||
System.err.println("txn abort failed: " + ae.toString());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="blocking_deadlocks.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="isolation.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Locks, Blocks, and Deadlocks </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Isolation</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
382
docs/gsg_txn/JAVA/logconfig.html
Normal file
382
docs/gsg_txn/JAVA/logconfig.html
Normal file
@@ -0,0 +1,382 @@
|
||||
<?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>Configuring the Logging Subsystem</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="logfileremoval.html" title="Removing Log Files" />
|
||||
<link rel="next" href="wrapup.html" title="Chapter 6. Summary and Examples" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Configuring the Logging Subsystem</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="logfileremoval.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="wrapup.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="logconfig"></a>Configuring the Logging Subsystem</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You can configure the following aspects of the logging
|
||||
subsystem:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Size of the log files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Size of the logging subsystem's region.
|
||||
See <a href="logconfig.html#logregionsize">Configuring the Logging Region Size</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Maintain logs entirely in-memory.
|
||||
See <a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Size of the log buffer in memory.
|
||||
See <a href="logconfig.html#logbuffer">Setting the In-Memory Log Buffer Size</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
On-disk location of your log files. See
|
||||
<a href="enabletxn.html#splittingdata">Identifying Specific File Locations</a>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="logfilesize"></a>Setting the Log File Size</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Whenever a pre-defined amount of data is written to a
|
||||
log file (10 MB by default), DB stops using the
|
||||
current log file and starts writing to a new file.
|
||||
You can change the maximum amount of data contained in each
|
||||
log file by using the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setMaxLogFileSize()</tt>
|
||||
method.
|
||||
</span>
|
||||
Note that this method can be used at any time
|
||||
during an application's lifetime.
|
||||
</p>
|
||||
<p>
|
||||
Setting the log file size to something larger than its
|
||||
default value is largely a matter of
|
||||
convenience and a reflection of the application's
|
||||
preference in backup media and frequency. However, if
|
||||
you set the log file size too low relative to your
|
||||
application's traffic patterns, you can cause
|
||||
yourself trouble.
|
||||
</p>
|
||||
<p>
|
||||
From a performance perspective, setting the log file
|
||||
size to a low value can cause your active transactions to
|
||||
pause their writing activities more frequently than would
|
||||
occur with larger log file sizes. Whenever a
|
||||
transaction completes the log buffer is flushed to
|
||||
disk. Normally other transactions can continue to
|
||||
write to the log buffer while this flush is in
|
||||
progress. However, when one log file is being closed
|
||||
and another created, all transactions must cease
|
||||
writing to the log buffer until the switch over is
|
||||
completed.
|
||||
</p>
|
||||
<p>
|
||||
Beyond performance concerns, using smaller log files
|
||||
can cause you to use more physical files on disk.
|
||||
As a result, your application could run out
|
||||
of log sequence numbers, depending on how busy your
|
||||
application is.
|
||||
</p>
|
||||
<p>
|
||||
Every log file is identified with a 10 digit number.
|
||||
Moreover, the maximum number of log files that your application
|
||||
is allowed to create in its lifetime is 2,000,000,000.
|
||||
</p>
|
||||
<p>
|
||||
For example, if your application performs 6,000 transactions per
|
||||
second for 24 hours a day, and you are logging 500 bytes of
|
||||
data per transaction into 10 MB log files, then you
|
||||
will run out of log files in around 221 years:
|
||||
</p>
|
||||
<pre class="programlisting"> (10 * 2^20 * 2000000000) / (6000 * 500 * 365 * 60 *60 * 24) = 221 </pre>
|
||||
<p>
|
||||
However, if you were writing 2000 bytes of data per
|
||||
transaction, and using 1 MB log files, then the same
|
||||
formula shows you running out of log files in 5 years time.
|
||||
</p>
|
||||
<p>
|
||||
All of these time frames are quite long, to be sure,
|
||||
but if you do run out of log files after, say, 5 years
|
||||
of continuous operations, then you must reset your log
|
||||
sequence numbers. To do so:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Backup your databases as if to prepare for
|
||||
catastrophic failure. See
|
||||
<a href="backuprestore.html">Backup Procedures</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Reset the log file's sequence number using the
|
||||
<span><b class="command">db_load</b></span> utility's
|
||||
<tt class="literal">-r</tt> option.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Remove all of the log files from your
|
||||
environment. Note that this is the only
|
||||
situation in which all of the log files are
|
||||
removed from an environment; in all other
|
||||
cases, at least a single log file is retained.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Restart your application.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="logregionsize"></a>Configuring the Logging Region Size</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The logging subsystem's default region size is 60 KB. The
|
||||
logging region is used to store filenames, and so you may
|
||||
need to increase its size if a large number of files (that
|
||||
is, if you have a very large number of databases) will
|
||||
be opened and registered with DB's log manager.
|
||||
</p>
|
||||
<p>
|
||||
You can set the size of your logging region by using the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setLogRegionSize()</tt>
|
||||
</span>
|
||||
method. Note that this method can only be called before the
|
||||
first environment handle for your application is opened.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="inmemorylogging"></a>Configuring In-Memory Logging</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
It is possible to configure your logging subsystem such
|
||||
that logs are maintained entirely in memory. When
|
||||
you do this, you give up your transactional durability
|
||||
guarantee. Without log files, you have no way to run
|
||||
recovery so any system or software failures that you might
|
||||
experience can corrupt your databases.
|
||||
</p>
|
||||
<p>
|
||||
However, by giving up your durability guarantees, you can
|
||||
greatly improve your application's throughput by avoiding
|
||||
the disk I/O necessary to write logging information to
|
||||
disk. In this case, you still retain your transactional
|
||||
atomicity, consistency, and isolation guarantees.
|
||||
</p>
|
||||
<p>
|
||||
To configure your logging subsystem to maintain your logs
|
||||
entirely in-memory:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Make sure your log buffer is capable of holding all
|
||||
log information that can accumulate during the longest
|
||||
running transaction. See <a href="logconfig.html#logbuffer">Setting the In-Memory Log Buffer Size</a> for details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Do not run normal recovery when you open your environment. In this configuration, there are no
|
||||
log files available against which you can run recovery. As a result, if you specify recovery
|
||||
when you open your environment, it is ignored.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Specify
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt>
|
||||
to the
|
||||
<tt class="methodname">EnvironmentConfig.setLogInMemory()</tt>
|
||||
</span>
|
||||
method. Note that you must specify this before
|
||||
your application opens its first environment
|
||||
handle.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
// Specify in-memory logging
|
||||
myEnvConfig.setLogInMemory(true);
|
||||
|
||||
// Specify the in-memory log buffer size.
|
||||
myEnvConfig.setLogBufferSize(10 * 1024 * 1024);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// From here, you open databases, create transactions and
|
||||
// perform database operations exactly as you would if you
|
||||
// were logging to disk. This part is omitted for brevity. </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="logbuffer"></a>Setting the In-Memory Log Buffer Size</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When your application is configured for on-disk logging
|
||||
(the default behavior for transactional applications), log
|
||||
information is stored in-memory until the storage space
|
||||
fills up, or a transaction commit forces the log
|
||||
information to be flushed to disk.
|
||||
</p>
|
||||
<p>
|
||||
It is possible to increase the amount of memory available
|
||||
to your file log buffer. Doing so improves throughput for
|
||||
long-running transactions, or for transactions that produce
|
||||
a large amount of data.
|
||||
</p>
|
||||
<p>
|
||||
When you have your logging subsystem configured to maintain
|
||||
your log entirely in memory (see
|
||||
<a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>), it is very important
|
||||
to configure your log buffer size because the log buffer
|
||||
must be capable of holding all log information that can
|
||||
accumulate during the longest running transaction.
|
||||
You must make sure that the in-memory log buffer size is
|
||||
large enough that no transaction will ever span the entire
|
||||
buffer. You must also avoid a state where the in-memory
|
||||
buffer is full and no space can be freed because a
|
||||
transaction that started the first log "file" is still
|
||||
active.
|
||||
</p>
|
||||
<p>
|
||||
When your logging subsystem is configured for on-disk
|
||||
logging, the default log buffer space is 32 KB. When
|
||||
in-memory logging is configured, the default log buffer
|
||||
space is 1 MB.
|
||||
</p>
|
||||
<p>
|
||||
You can increase your log buffer space using the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setLogBufferSize()</tt>
|
||||
</span>
|
||||
method. Note that this method can only be called before the
|
||||
first environment handle for your application is opened.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="logfileremoval.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="wrapup.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Removing Log Files </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 6. Summary and Examples</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
202
docs/gsg_txn/JAVA/logfileremoval.html
Normal file
202
docs/gsg_txn/JAVA/logfileremoval.html
Normal file
@@ -0,0 +1,202 @@
|
||||
<?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>Removing Log Files</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="hotfailover.html" title="Using Hot Failovers" />
|
||||
<link rel="next" href="logconfig.html" title="Configuring the Logging Subsystem" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Removing Log Files</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="hotfailover.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="logconfig.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="logfileremoval"></a>Removing Log Files</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
By default DB does not delete log files for you. For this reason,
|
||||
DB's log files will eventually grow to consume an
|
||||
unnecessarily large amount of disk space. To guard against
|
||||
this, you should periodically take administrative action to
|
||||
remove log files that are no longer in use by your application.
|
||||
</p>
|
||||
<p>
|
||||
You can remove a log file if all of the following are true:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
the log file is not involved in an active transaction.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
a checkpoint has been performed
|
||||
<span class="emphasis"><em>after</em></span> the log file was
|
||||
created.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
the log file is not the only log file in the
|
||||
environment.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
the log file that you want to remove has already been
|
||||
included in an offline or hot backup.
|
||||
Failure to observe this last condition can cause your
|
||||
backups to be unusable.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
DB provides several mechanisms to remove log files that
|
||||
meet all but the last criteria (DB has no way to know which
|
||||
log files have already been included in a backup). The
|
||||
following mechanisms make it easy to remove unneeded log files,
|
||||
but can result in an unusable backup if the log files are not first
|
||||
saved to your archive location. All of the following
|
||||
mechanisms automatically delete unneeded log files for you:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Run the <span><b class="command">db_archive</b></span> command line
|
||||
utility with the <tt class="literal">-d</tt> option.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
From within your application, call the
|
||||
|
||||
<span>
|
||||
<tt class="methodname">Environment.removeOldLogFiles()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<span>
|
||||
Specify <tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setLogAutoRemove()</tt>
|
||||
method. Note that setting this property affects
|
||||
all environment handles opened against the
|
||||
environment; not just the handle used to set
|
||||
the property.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Note that unlike the other log removal mechanisms
|
||||
identified here, this method actually causes log files
|
||||
to be removed on an on-going basis as they become
|
||||
unnecessary. This is extremely desirable behavior if
|
||||
what you want is to use the absolute minimum amount of
|
||||
disk space possible for your application. This
|
||||
mechanism <span class="emphasis"><em>will</em></span> leave you with
|
||||
the log files that are required to run normal recovery.
|
||||
However, it is highly likely that this mechanism will
|
||||
prevent you from running catastrophic recovery.
|
||||
</p>
|
||||
<p>
|
||||
Do NOT use this mechanism if you want to be able to
|
||||
perform catastrophic recovery, or if you want to be
|
||||
able to maintain a hot backup.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
In order to safely remove log files and still be able to
|
||||
perform catastrophic recovery, use the
|
||||
<span><b class="command">db_archive</b></span> command line utility as follows:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Run either a normal or hot backup as described in
|
||||
<a href="backuprestore.html">Backup Procedures</a>. Make
|
||||
sure that all of this data is safely stored to your
|
||||
backup media before continuing.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you have not already done so, perform a checkpoint.
|
||||
See <a href="filemanagement.html#checkpoints">Checkpoints</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you are maintaining a hot backup, perform the hot
|
||||
backup procedure as described in
|
||||
<a href="hotfailover.html">Using Hot Failovers</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Run the <span><b class="command">db_archive</b></span> command line
|
||||
utility with the <tt class="literal">-d</tt> option against
|
||||
your production environment.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Run the <span><b class="command">db_archive</b></span> command line
|
||||
utility with the <tt class="literal">-d</tt> option against
|
||||
your failover environment, if you are maintaining one.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="hotfailover.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="logconfig.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Using Hot Failovers </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Configuring the Logging Subsystem</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
203
docs/gsg_txn/JAVA/maxtxns.html
Normal file
203
docs/gsg_txn/JAVA/maxtxns.html
Normal file
@@ -0,0 +1,203 @@
|
||||
<?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>Configuring the Transaction Subsystem</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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="txnindices.html" title="Secondary Indices with Transaction Applications" />
|
||||
<link rel="next" href="txnconcurrency.html" title="Chapter 4. Concurrency" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Configuring the Transaction Subsystem</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnindices.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnconcurrency.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="maxtxns"></a>Configuring the Transaction Subsystem</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Most of the configuration activities that you need to perform
|
||||
for your transactional DB application will involve the
|
||||
locking and logging subsystems. See
|
||||
<a href="txnconcurrency.html">Concurrency</a>
|
||||
and
|
||||
<a href="filemanagement.html">Managing DB Files</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
However, there are a couple of things that you can do to
|
||||
configure your transaction subsystem directly. These things
|
||||
are:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Configure the maximum number of simultaneous
|
||||
transactions needed by your application.
|
||||
In general, you should not need to do this unless you
|
||||
use deeply nested transactions or you have many threads all
|
||||
of which have active transactions. In addition, you may
|
||||
need to a higher maximum number of transactions if you
|
||||
are using snapshot isolation. See
|
||||
<a href="isolation.html#sisolation_maxtxn">Snapshot Isolation Transactional Requirements</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
By default, your application can support 20 active
|
||||
transactions.
|
||||
</p>
|
||||
<p>
|
||||
You can set the maximum number of simultaneous
|
||||
transactions supported by your application using
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setTxnMaxActive()</tt>.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
If your application has exceeded this maximum value,
|
||||
then any attempt to begin a new transaction will fail.
|
||||
</p>
|
||||
<p>
|
||||
This value can also be set using the
|
||||
<tt class="literal">DB_CONFIG</tt> file's
|
||||
<tt class="literal">set_tx_max</tt> parameter. Remember that
|
||||
the <tt class="literal">DB_CONFIG</tt> must reside in your
|
||||
environment home directory.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<p>
|
||||
<span>
|
||||
Configure the timeout value for your transactions.
|
||||
</span>
|
||||
|
||||
|
||||
This value represents the longest period of time a
|
||||
transaction can be active. Note, however, that
|
||||
transaction timeouts are checked only when DB
|
||||
examines its lock tables for blocked locks
|
||||
(see <a href="blocking_deadlocks.html">Locks, Blocks, and Deadlocks</a>
|
||||
for more information). Therefore, a transaction's timeout can
|
||||
have expired, but the application will not be notified until DB
|
||||
has a reason to examine its lock tables.
|
||||
</p>
|
||||
<p>
|
||||
Be aware that some transactions may be
|
||||
inappropriately timed out before the transaction has a
|
||||
chance to complete. You should therefore use this
|
||||
mechanism only if you know your application
|
||||
might have unacceptably long transactions and
|
||||
you want to make sure your application will
|
||||
not stall during their execution.
|
||||
(This might happen if, for example, your
|
||||
transaction blocks or requests too much
|
||||
data.)
|
||||
</p>
|
||||
<p>
|
||||
Note that by default transaction timeouts are set to 0 seconds, which means that they never time
|
||||
out.
|
||||
</p>
|
||||
<p>
|
||||
To set the maximum timeout value for your transactions,
|
||||
use the
|
||||
|
||||
|
||||
<span><tt class="methodname">EnvironmentConfig.setTxnTimeout()</tt></span>
|
||||
method. This method configures the entire
|
||||
environment; not just the handle used to set the
|
||||
configuration. Further, this value may
|
||||
be set at any time during the application's
|
||||
lifetime. <span>(Use
|
||||
<tt class="methodname">Environment.setConfig()</tt> to
|
||||
set this value after the environment has been
|
||||
opened.)</span>
|
||||
</p>
|
||||
<p>
|
||||
This value can also be set using the
|
||||
<tt class="literal">DB_CONFIG</tt> file's
|
||||
<tt class="literal">set_txn_timeout</tt> parameter.
|
||||
</p>
|
||||
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.LockDetectMode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setTransactional(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
|
||||
// Configure a maximum transaction timeout of 1 second.
|
||||
myEnvConfig.setTxnTimeout(1000000);
|
||||
// Configure 40 maximum transactions.
|
||||
myEnv.setTxnMaxActive(40);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// From here, you open your databases (or store), proceed with your
|
||||
// database or store operations, and respond to deadlocks as is
|
||||
// normal (omitted for brevity).
|
||||
|
||||
...</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnindices.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txnconcurrency.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Secondary Indices with Transaction Applications </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 4. Concurrency</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
139
docs/gsg_txn/JAVA/nestedtxn.html
Normal file
139
docs/gsg_txn/JAVA/nestedtxn.html
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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>Nested Transactions</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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="autocommit.html" title="Auto Commit" />
|
||||
<link rel="next" href="txncursor.html" title="Transactional Cursors" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Nested Transactions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="autocommit.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txncursor.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="nestedtxn"></a>Nested Transactions</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
A <span class="emphasis"><em>nested transaction</em></span> is used to provide a
|
||||
transactional guarantee for a subset of operations performed within
|
||||
the scope of a larger transaction. Doing this allows you to commit
|
||||
and abort the subset of operations independently of the larger
|
||||
transaction.
|
||||
</p>
|
||||
<p>
|
||||
The rules to the usage of a nested transaction are as follows:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
While the nested (child) transaction is active, the parent
|
||||
transaction may not perform any operations other than to commit
|
||||
or abort, or to create more child transactions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Committing a nested transaction has no effect on the state
|
||||
of the parent transaction. The parent transaction is still
|
||||
uncommitted. However, the parent transaction can now
|
||||
see any modifications made by the child transaction.
|
||||
Those modifications, of course, are still hidden to all
|
||||
other transactions until the parent also commits.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Likewise, aborting the nested transaction has no effect on
|
||||
the state of the parent transaction. The only result of the
|
||||
abort is that neither the parent nor any
|
||||
other transactions will see any of the
|
||||
database modifications performed under the protection of the
|
||||
nested transaction.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If the parent transaction commits or aborts while it has
|
||||
active children, the child transactions are resolved in the
|
||||
same way as the parent. That is, if the parent aborts, then
|
||||
the child transactions abort as well. If the parent commits,
|
||||
then whatever modifications have been performed by the child
|
||||
transactions are also committed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The locks held by a nested transaction are not released when
|
||||
that transaction commits. Rather, they are now held by the
|
||||
parent transaction until such a time as that parent commits.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Any database modifications performed by the nested transaction
|
||||
are not visible outside of the larger encompassing
|
||||
transaction until such a time as that parent transaction is
|
||||
committed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The depth of the nesting that you can achieve with nested
|
||||
transaction is limited only by memory.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
To create a nested transaction, simply pass the parent transaction's
|
||||
handle when you created the nested transaction's handle. For
|
||||
example:
|
||||
</p>
|
||||
<pre class="programlisting"> // parent transaction
|
||||
Transaction parentTxn = myEnv.beginTransaction(null, null);
|
||||
// child transaction
|
||||
Transaction childTxn = myEnv.beginTransaction(parentTxn, null); </pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="autocommit.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txncursor.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Auto Commit </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Transactional Cursors</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
88
docs/gsg_txn/JAVA/perftune-intro.html
Normal file
88
docs/gsg_txn/JAVA/perftune-intro.html
Normal file
@@ -0,0 +1,88 @@
|
||||
<?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>Performance Tuning</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="recovery-intro.html" title="Recoverability" />
|
||||
<link rel="next" href="enabletxn.html" title="Chapter 2. Enabling Transactions" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Performance Tuning</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="recovery-intro.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="enabletxn.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="perftune-intro"></a>Performance Tuning</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
From a performance perspective, the use of transactions is not free.
|
||||
Depending on how you configure them, transaction commits
|
||||
usually require your application to perform disk I/O that a non-transactional
|
||||
application does not perform. Also, for multi-threaded
|
||||
<span>and
|
||||
multi-process</span> applications, the use of transactions can
|
||||
result in increased lock contention due to extra locking
|
||||
requirements driven by transactional isolation guarantees.
|
||||
</p>
|
||||
<p>
|
||||
There is therefore a performance tuning component to transactional applications
|
||||
that is not applicable for non-transactional applications (although
|
||||
some tuning considerations do exist whether or not your application uses
|
||||
transactions). Where appropriate, these tuning considerations are
|
||||
introduced in the following chapters.
|
||||
|
||||
<span>
|
||||
However, for a more complete description of them, see the
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/tune.html" target="_top">
|
||||
Transaction tuning
|
||||
</a>
|
||||
and
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/throughput.html" target="_top">
|
||||
Transaction throughput
|
||||
</a>
|
||||
sections of the <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="recovery-intro.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="enabletxn.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Recoverability </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 2. Enabling Transactions</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
227
docs/gsg_txn/JAVA/preface.html
Normal file
227
docs/gsg_txn/JAVA/preface.html
Normal file
@@ -0,0 +1,227 @@
|
||||
<?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>Preface</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="next" href="introduction.html" title="Chapter 1. Introduction" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Preface</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="preface" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="preface"></a>Preface</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="preface.html#conventions">Conventions Used in this Book</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="preface.html#moreinfo">For More Information</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
This document describes how to use transactions with your Berkeley DB
|
||||
applications. It is intended to describe how to
|
||||
transaction protect your application's data. The APIs used to perform this task
|
||||
are described here, as are the environment infrastructure and administrative tasks
|
||||
required by a transactional application. This book also
|
||||
describes multi-threaded <span>and
|
||||
multi-process</span> DB applications and the requirements they
|
||||
have for deadlock detection.
|
||||
</p>
|
||||
<p>
|
||||
This book is aimed at the software engineer responsible for writing a
|
||||
transactional DB application.
|
||||
</p>
|
||||
<p>
|
||||
This book assumes that you have already read and understood the
|
||||
concepts contained in the
|
||||
<span><i class="citetitle">Getting Started with Berkeley DB</i>
|
||||
guide.</span>
|
||||
|
||||
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="conventions"></a>Conventions Used in this Book</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The following typographical conventions are used within in this manual:
|
||||
</p>
|
||||
<p>
|
||||
Class names are represented in <tt class="classname">monospaced font</tt>, as are <tt class="methodname">method
|
||||
names</tt>. For example:
|
||||
|
||||
|
||||
|
||||
<span>"The <tt class="methodname">Environment()</tt>
|
||||
constructor returns an <tt class="classname">Environment</tt> class object."</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Variable or non-literal text is presented in <span class="emphasis"><em>italics</em></span>. For example: "Go to your
|
||||
<span class="emphasis"><em>DB_INSTALL</em></span> directory."
|
||||
</p>
|
||||
<p>
|
||||
Program examples are displayed in a <tt class="classname">monospaced font</tt> on a shaded background.
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">import com.sleepycat.db.DatabaseConfig;
|
||||
|
||||
...
|
||||
|
||||
// Allow the database to be created.
|
||||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||||
myDbConfig.setAllowCreate(true);</pre>
|
||||
<p>
|
||||
In some situations, programming examples are updated from one chapter to the next. When
|
||||
this occurs, the new code is presented in <b class="userinput"><tt>monospaced bold</tt></b> font. For example:
|
||||
</p>
|
||||
<pre class="programlisting"><b class="userinput"><tt>import com.sleepycat.db.Database;</tt></b>
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
|
||||
...
|
||||
|
||||
// Allow the database to be created.
|
||||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||||
myDbConfig.setAllowCreate(true);
|
||||
<b class="userinput"><tt>Database myDb = new Database("mydb.db", null, myDbConfig);</tt></b> </pre>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Finally, notes of special interest are represented using a note block such
|
||||
as this.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="moreinfo"></a>For More Information</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Beyond this manual, you may also find the following sources of information useful when building a
|
||||
transactional DB application:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg/JAVA/index.html" target="_top">
|
||||
Getting Started with Berkeley DB for Java
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg_db_rep/JAVA/index.html" target="_top">
|
||||
Berkeley DB Getting Started with Replicated Applications for Java
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/toc.html" target="_top">
|
||||
Berkeley DB Programmer's Reference Guide
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/java/index.html" target="_top">
|
||||
Berkeley DB Javadoc
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/collections/tutorial/index.html" target="_top">
|
||||
Berkeley DB Collections Tutorial
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Getting Started with Berkeley DB Transaction Processing </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 1. Introduction</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/gsg_txn/JAVA/readblock.jpg
Normal file
BIN
docs/gsg_txn/JAVA/readblock.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
157
docs/gsg_txn/JAVA/readmodifywrite.html
Normal file
157
docs/gsg_txn/JAVA/readmodifywrite.html
Normal file
@@ -0,0 +1,157 @@
|
||||
<?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>Read/Modify/Write</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="txn_ccursor.html" title="Transactional Cursors and Concurrent Applications" />
|
||||
<link rel="next" href="txnnowait.html" title="No Wait on Blocks" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Read/Modify/Write</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txn_ccursor.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Concurrency</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnnowait.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="readmodifywrite"></a>Read/Modify/Write</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If you are retrieving
|
||||
|
||||
|
||||
<span>a record from the database or a class from the store</span>
|
||||
for the purpose of modifying or deleting it, you should declare
|
||||
a read-modify-write cycle at the time that you read the
|
||||
<span>record.</span>
|
||||
|
||||
Doing so causes DB to obtain write locks (instead of a read
|
||||
locks) at the time of the read. This helps to prevent deadlocks by
|
||||
preventing another transaction from acquiring a read lock on the same
|
||||
record while the read-modify-write cycle is in progress.
|
||||
</p>
|
||||
<p>
|
||||
Note that declaring a read-modify-write cycle may actually increase the amount of blocking that your
|
||||
application sees, because readers immediately obtain write locks and write locks cannot be shared. For this
|
||||
reason, you should use read-modify-write cycles only if you are seeing a large amount of deadlocking
|
||||
occurring in your application.
|
||||
</p>
|
||||
<p>
|
||||
In order to declare a read/modify/write cycle when you perform a
|
||||
read operation,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
specify
|
||||
<tt class="classname">com.sleepycat.db.LockMode.RMW</tt>
|
||||
|
||||
to the database, cursor,
|
||||
<tt class="classname">PrimaryIndex</tt>, or
|
||||
<tt class="classname">SecondaryIndex</tt> get method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">// Begin the deadlock retry loop as is normal.
|
||||
while (retry_count < MAX_DEADLOCK_RETRIES) {
|
||||
try {
|
||||
txn = myEnv.beginTransaction(null, null);
|
||||
|
||||
...
|
||||
// key and data are DatabaseEntry objects.
|
||||
// Their usage is omitted for brevity.
|
||||
...
|
||||
|
||||
// Read the data. Declare the read/modify/write cycle here
|
||||
myDatabase.get(txn, key, data, LockMode.RMW);
|
||||
|
||||
|
||||
// Put the data. Note that you do not have to provide any
|
||||
// additional flags here due to the read/modify/write
|
||||
// cycle. Simply put the data and perform your deadlock
|
||||
// detection as normal.
|
||||
myDatabase.put(txn, key, data);
|
||||
txn.commit();
|
||||
return 0;
|
||||
} catch (DeadlockException de) {
|
||||
// Deadlock detection and exception handling omitted
|
||||
// for brevity
|
||||
... </pre>
|
||||
<p>
|
||||
Or, with the DPL:
|
||||
</p>
|
||||
<pre class="programlisting">// Begin the deadlock retry loop as is normal
|
||||
while (retry_count < MAX_DEADLOCK_RETRIES) {
|
||||
try {
|
||||
txn = myEnv.beginTransaction(null, null);
|
||||
|
||||
...
|
||||
// 'store' is an EntityStore and 'Inventory' is an entity class
|
||||
// Their usage and implementation is omitted for brevity.
|
||||
...
|
||||
|
||||
// Read the data, using the PrimaryIndex for the entity object
|
||||
PrimaryIndex<String,Inventory> pi =
|
||||
store.getPrimaryIndex(String.class, Inventory.class);
|
||||
Inventory iv = pi.get(txn, "somekey", LockMode.RMW);
|
||||
|
||||
// Do something to the retreived object
|
||||
|
||||
|
||||
// Put the object. Note that you do not have to provide any
|
||||
// additional flags here due to the read/modify/write
|
||||
// cycle. Simply put the data and perform your deadlock
|
||||
// detection as normal.
|
||||
|
||||
pi.put(txn, iv);
|
||||
txn.commit();
|
||||
return 0;
|
||||
|
||||
} catch (DeadlockException de) {
|
||||
// Deadlock detection and exception handling omitted
|
||||
// for brevity
|
||||
... </pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txn_ccursor.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="txnnowait.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Transactional Cursors and Concurrent Applications </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> No Wait on Blocks</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
104
docs/gsg_txn/JAVA/recovery-intro.html
Normal file
104
docs/gsg_txn/JAVA/recovery-intro.html
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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>Recoverability</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="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="previous" href="introduction.html" title="Chapter 1. Introduction" />
|
||||
<link rel="next" href="perftune-intro.html" title="Performance Tuning" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Recoverability</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 1. Introduction</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="perftune-intro.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="recovery-intro"></a>Recoverability</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
An important part of DB's transactional guarantees is durability.
|
||||
<span class="emphasis"><em>Durability</em></span> means that once a
|
||||
transaction has been committed, the database modifications performed
|
||||
under its protection will not be lost due to system failure.
|
||||
</p>
|
||||
<p>
|
||||
In order to provide the transactional durability guarantee,
|
||||
DB uses a write-ahead logging system. Every operation performed on
|
||||
your databases is described in a log before it is performed on
|
||||
your databases. This is done in order to ensure that an operation can be
|
||||
recovered in the event of an untimely application
|
||||
or system failure.
|
||||
</p>
|
||||
<p>
|
||||
<span>
|
||||
Beyond logging, another important aspect of durability is
|
||||
recoverability. That is, backup and restore. </span>
|
||||
|
||||
DB supports a normal recovery that runs against a subset of
|
||||
your log files. This is a routine procedure used whenever your
|
||||
environment is first opened upon application startup, and it is intended to
|
||||
ensure that your database is in a consistent state. DB also
|
||||
supports archival backup and recovery in the case of
|
||||
catastrophic failure, such as the loss of a physical disk
|
||||
drive.
|
||||
</p>
|
||||
<p>
|
||||
This book describes several different backup procedures
|
||||
you can use to protect your on-disk data. These procedures
|
||||
range from simple offline backup strategies to hot failovers. Hot failovers
|
||||
provide not only a backup mechanism, but
|
||||
also a way to recover from a fatal hardware failure.
|
||||
</p>
|
||||
<p>
|
||||
This book also describes the recovery procedures you should use
|
||||
for each of the backup strategies that you might employ.
|
||||
</p>
|
||||
<p>
|
||||
For a detailed description of backup and restore procedures, see
|
||||
<span>
|
||||
<a href="filemanagement.html">Managing DB Files</a>.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="introduction.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="perftune-intro.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 1. Introduction </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Performance Tuning</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
298
docs/gsg_txn/JAVA/recovery.html
Normal file
298
docs/gsg_txn/JAVA/recovery.html
Normal file
@@ -0,0 +1,298 @@
|
||||
<?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>Recovery Procedures</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="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
<link rel="previous" href="backuprestore.html" title="Backup Procedures" />
|
||||
<link rel="next" href="architectrecovery.html" title="Designing Your Application for Recovery" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Recovery Procedures</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="backuprestore.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 5. Managing DB Files</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="architectrecovery.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="recovery"></a>Recovery Procedures</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
DB supports two types of recovery:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Normal recovery, which is run when your environment is
|
||||
opened upon application startup, examines only those
|
||||
log records needed to bring the databases to a consistent
|
||||
state since the last checkpoint. Normal recovery
|
||||
starts with any logs used by any transactions active at
|
||||
the time of the last checkpoint, and examines all logs
|
||||
from then to the current logs.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Catastrophic recovery, which is performed in the same
|
||||
way that normal recovery is except that it examines
|
||||
all available log files. You use catastrophic recovery
|
||||
to restore your databases from a previously created backup.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Of these two, normal recovery should be considered a routine
|
||||
matter; in fact you should run normal
|
||||
recovery whenever you start up your application.
|
||||
</p>
|
||||
<p>
|
||||
Catastrophic recovery is run whenever you have lost or
|
||||
corrupted your database files and you want to restore from a
|
||||
backup. You also run catastrophic recovery when
|
||||
you create a hot backup
|
||||
(see <a href="hotfailover.html">Using Hot Failovers</a> for more information).
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="normalrecovery"></a>Normal Recovery</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Normal recovery examines the contents of your environment's
|
||||
log files, and uses this information to ensure that your
|
||||
database files are consistent relative to the
|
||||
information contained in the log files.
|
||||
</p>
|
||||
<p>
|
||||
Normal recovery also recreates your environment's region files.
|
||||
This has the desired effect of clearing any unreleased locks
|
||||
that your application may have held at the time of an
|
||||
unclean application shutdown.
|
||||
</p>
|
||||
<p>
|
||||
Normal recovery is run only against those log files created
|
||||
since the time of your last checkpoint. For this reason,
|
||||
your recovery time is dependent on how much data has been
|
||||
written since the last checkpoint, and therefore on how
|
||||
much log file information there is to examine. If you run
|
||||
checkpoints infrequently, then normal recovery can
|
||||
take a relatively long time.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
You should run normal recovery every
|
||||
time you perform application startup.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
To run normal recovery:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Make sure all your environment handles are closed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Normal recovery <span class="emphasis"><em>must
|
||||
be</em></span> single-threaded.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Specify <tt class="literal">true</tt> to
|
||||
<tt class="methodname">EnvironmentConfig.setRunRecovery()</tt>
|
||||
when you open your environment.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
You can also run recovery by pausing or shutting down your
|
||||
application and using the <span><b class="command">db_recover</b></span>
|
||||
command line utility.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
|
||||
...
|
||||
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
// Run normal recovery
|
||||
myEnvConfig.setRunRecovery(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// All other operations are identical from here. Notice, however,
|
||||
// that we have not created any other threads of control before
|
||||
// recovery is complete. You want to run recovery for
|
||||
// the first thread in your application that opens an environment,
|
||||
// but not for any subsequent threads.
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="catastrophicrecovery"></a>Catastrophic Recovery</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Use catastrophic recovery when you are
|
||||
recovering your databases from a previously created backup.
|
||||
Note that to restore your databases from a previous backup, you
|
||||
should copy the backup to a new environment directory, and
|
||||
then run catastrophic recovery. Failure to do so can lead to
|
||||
the internal database structures being out of sync with your log files.
|
||||
</p>
|
||||
<p>
|
||||
Catastrophic recovery must be run single-threaded.
|
||||
</p>
|
||||
<p>
|
||||
To run catastrophic recovery:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Shutdown all database operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Restore the backup to an empty directory.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Specify <tt class="literal">true</tt> to
|
||||
<tt class="methodname">EnvironmentConfig.setRunRecoveryFatal()</tt>
|
||||
when you open your environment. This environment
|
||||
open must be single-threaded.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
You can also run recovery by pausing or shutting down your
|
||||
application and using the <span><b class="command">db_recover</b></span>
|
||||
command line utility with the the <tt class="literal">-c</tt> option.
|
||||
</p>
|
||||
<p>
|
||||
Note that catastrophic recovery examines every available
|
||||
log file — not just those log files created since the
|
||||
last checkpoint as is the case for normal recovery. For this reason,
|
||||
catastrophic recovery is likely to take longer than does
|
||||
normal recovery.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
|
||||
...
|
||||
|
||||
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
// Run catastrophic recovery
|
||||
<b class="userinput"><tt>myEnvConfig.setRunFatalRecovery(true);</tt></b>
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="backuprestore.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="filemanagement.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="architectrecovery.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Backup Procedures </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Designing Your Application for Recovery</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
199
docs/gsg_txn/JAVA/reversesplit.html
Normal file
199
docs/gsg_txn/JAVA/reversesplit.html
Normal file
@@ -0,0 +1,199 @@
|
||||
<?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>Reverse BTree Splits</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="txnnowait.html" title="No Wait on Blocks" />
|
||||
<link rel="next" href="filemanagement.html" title="Chapter 5. Managing DB Files" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Reverse BTree Splits</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnnowait.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Concurrency</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="filemanagement.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="reversesplit"></a>Reverse BTree Splits</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
If your application is using the Btree access method, and your
|
||||
application is repeatedly deleting then adding records to your
|
||||
database, then you might be able to reduce lock contention by
|
||||
turning off reverse Btree splits.
|
||||
</p>
|
||||
<p>
|
||||
As pages are emptied in a database, DB attempts to
|
||||
delete empty pages in order to keep
|
||||
the database as small as possible and minimize search time.
|
||||
Moreover, when a page in the database fills
|
||||
up, DB, of course, adds additional pages
|
||||
to make room for more data.
|
||||
</p>
|
||||
<p>
|
||||
Adding and deleting pages in the database requires that the
|
||||
writing thread lock the parent page. Consequently, as the
|
||||
number of pages in your database diminishes, your application
|
||||
will see increasingly more lock contention; the maximum level
|
||||
of concurrency in a database of two pages is far smaller than
|
||||
that in a database of 100 pages, because there are fewer pages
|
||||
that can be locked.
|
||||
</p>
|
||||
<p>
|
||||
Therefore, if you prevent the database from being reduced to a
|
||||
minimum number of pages, you can improve your application's
|
||||
concurrency throughput. Note, however, that you should do so
|
||||
only if your application tends to delete and then add the same
|
||||
data. If this is not the case, then preventing reverse Btree
|
||||
splits can harm your database search time.
|
||||
</p>
|
||||
<p>
|
||||
To turn off reverse Btree splits,
|
||||
|
||||
<span>
|
||||
set
|
||||
<tt class="methodname">DatabaseConfig.setReverseSplitOff()</tt>.
|
||||
to <tt class="literal">true</tt>.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Open the database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
|
||||
// Set BTree reverse split to off
|
||||
dbConfig.setReverseSplitOff(true);
|
||||
|
||||
myDatabase = myEnv.openDatabase(null, // txn handle
|
||||
"sampleDatabase", // db file name
|
||||
"null", // db name
|
||||
dbConfig);
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
<p>
|
||||
Or, if you are using the DPL:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
EntityStore myStore = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Configure the store.
|
||||
StoreConfig myStoreConfig = new StoreConfig();
|
||||
myStoreConfig.setAllowCreate(true);
|
||||
myStoreConfig.setTransactional(true);
|
||||
|
||||
// Configure the underlying database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setAllowCreate(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
|
||||
// Set BTree reverse split to off
|
||||
dbConfig.setReverseSplitOff(true);
|
||||
|
||||
// Instantiate the store
|
||||
myStore = new EntityStore(myEnv, "store_name", myStoreConfig);
|
||||
|
||||
// Set the DatabaseConfig object, so that the underlying
|
||||
// database is configured for uncommitted reads.
|
||||
myStore.setPrimaryConfig(SomeEntityClass.class, dbConfig);
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnnowait.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="filemanagement.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">No Wait on Blocks </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Chapter 5. Managing DB Files</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/gsg_txn/JAVA/rwlocks1.jpg
Normal file
BIN
docs/gsg_txn/JAVA/rwlocks1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
docs/gsg_txn/JAVA/simplelock.jpg
Normal file
BIN
docs/gsg_txn/JAVA/simplelock.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
244
docs/gsg_txn/JAVA/txn_ccursor.html
Normal file
244
docs/gsg_txn/JAVA/txn_ccursor.html
Normal file
@@ -0,0 +1,244 @@
|
||||
<?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. <span>This is true of both
|
||||
base API and DPL cursors.</span>
|
||||
</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. <span>This is
|
||||
true of both base API and DPL cursors.</span>
|
||||
</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
|
||||
<span>or store</span> 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">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.CursorConfig;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setTransactional(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Open the database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
dbConfig.setReadUncommitted(true); // Enable uncommitted reads.
|
||||
myDatabase = myEnv.openDatabase(null, // txn handle
|
||||
"sampleDatabase", // db file name
|
||||
null, // db name
|
||||
dbConfig);
|
||||
|
||||
// Open the transaction. Note that this is a degree 3
|
||||
// transaction.
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
// Use the transaction handle here
|
||||
// Get our cursor. Note that we pass the transaction
|
||||
// handle here. Note also that we cause the cursor
|
||||
// to perform uncommitted reads.
|
||||
CursorConfig cconfig = new CursorConfig();
|
||||
cconfig.setReadUncommitted(true);
|
||||
cursor = db.openCursor(txn, cconfig);
|
||||
|
||||
// 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>
|
||||
<p>
|
||||
If you are using the DPL:
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
|
||||
import com.sleepycat.db.CursorConfig;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import com.sleepycat.persist.EntityCursor;
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.PrimaryIndex;
|
||||
import com.sleepycat.persist.StoreConfig;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
...
|
||||
|
||||
EntityStore myStore = null;
|
||||
Environment myEnv = null;
|
||||
PrimaryIndex<String,AnEntityClass> pKey;
|
||||
|
||||
try {
|
||||
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setTransactional(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Set up the entity store
|
||||
StoreConfig myStoreConfig = new StoreConfig();
|
||||
myStoreConfig.setAllowCreate(true);
|
||||
myStoreConfig.setTransactional(true);
|
||||
|
||||
// Configure uncommitted reads
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
dbConfig.setAllowCreate(true);
|
||||
dbConfig.setReadUncommitted(true); // Enable uncommitted reads.
|
||||
|
||||
// Instantiate the store
|
||||
myStore = new EntityStore(myEnv, storeName, myStoreConfig);
|
||||
|
||||
// Set the DatabaseConfig object, so that the underlying
|
||||
// database is configured for uncommitted reads.
|
||||
myStore.setPrimaryConfig(AnEntityClass.class, myDbConfig);
|
||||
|
||||
// Open the transaction. Note that this is a degree 3
|
||||
// transaction.
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
|
||||
//Configure our cursor for uncommitted reads.
|
||||
CursorConfig cconfig = new CursorConfig();
|
||||
cconfig.setReadUncommitted(true);
|
||||
|
||||
// Get our cursor. Note that we pass the transaction
|
||||
// handle here. Note also that we cause the cursor
|
||||
// to perform uncommitted reads.
|
||||
EntityCursor<AnEntityClass> cursor = pKey.entities(txn, cconfig);
|
||||
|
||||
try {
|
||||
// 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>
|
||||
372
docs/gsg_txn/JAVA/txnconcurrency.html
Normal file
372
docs/gsg_txn/JAVA/txnconcurrency.html
Normal file
@@ -0,0 +1,372 @@
|
||||
<?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>Chapter 4. Concurrency</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="maxtxns.html" title="Configuring the Transaction Subsystem" />
|
||||
<link rel="next" href="blocking_deadlocks.html" title="Locks, Blocks, and Deadlocks" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 4. Concurrency</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="maxtxns.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="blocking_deadlocks.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="txnconcurrency"></a>Chapter 4. Concurrency</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnconcurrency.html#concurrenthandles">Which DB Handles are Free-Threaded</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="blocking_deadlocks.html">Locks, Blocks, and Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#locks">Locks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#blocks">Blocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="blocking_deadlocks.html#deadlocks">Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="lockingsubsystem.html">The Locking Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#configuringlock">Configuring the Locking Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#configdeadlkdetect">Configuring Deadlock Detection</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="lockingsubsystem.html#deadlockresolve">Resolving Deadlocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="isolation.html">Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#degreesofisolation">Supported Degrees of Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#dirtyreads">Reading Uncommitted Data</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#readcommitted">Committed Reads</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="isolation.html#snapshot_isolation">Using Snapshot Isolation</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txn_ccursor.html">Transactional Cursors and Concurrent Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txn_ccursor.html#cursordirtyreads">Using Cursors with Uncommitted Data</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="readmodifywrite.html">Read/Modify/Write</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnnowait.html">No Wait on Blocks</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="reversesplit.html">Reverse BTree Splits</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
DB offers a great deal of support for multi-threaded
|
||||
<span>
|
||||
and multi-process
|
||||
</span>
|
||||
applications even when transactions are not in use. Many of DB's
|
||||
handles are
|
||||
thread-safe<span>, or
|
||||
can be made thread-safe by providing the appropriate flag at handle creation time,</span>
|
||||
and DB provides a
|
||||
flexible locking subsystem for managing databases in a concurrent
|
||||
application. Further, DB provides a robust mechanism for
|
||||
detecting and responding to deadlocks. All of these concepts are
|
||||
explored in this chapter.
|
||||
</p>
|
||||
<p>
|
||||
Before continuing, it is useful to define a few terms that will appear
|
||||
throughout this chapter:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<span class="emphasis"><em>Thread of control</em></span>
|
||||
</p>
|
||||
<p>
|
||||
Refers to a thread that is performing work in your application.
|
||||
Typically, in this book that thread will be performing DB
|
||||
operations.
|
||||
</p>
|
||||
<p>
|
||||
Note that this term can also be taken to mean a separate process
|
||||
that is performing work — DB supports multi-process
|
||||
operations on your databases.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="emphasis"><em>Locking</em></span>
|
||||
</p>
|
||||
<p>
|
||||
When a thread of control obtains
|
||||
access to a shared resource, it is said to be
|
||||
<span class="emphasis"><em>locking</em></span> that resource. Note that
|
||||
DB supports both exclusive and non-exclusive locks. See
|
||||
<a href="blocking_deadlocks.html#locks">Locks</a> for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="emphasis"><em>Free-threaded</em></span>
|
||||
</p>
|
||||
<p>
|
||||
Data structures and objects are free-threaded if they can be
|
||||
shared across threads of control without any explicit locking on
|
||||
the part of the application. Some books, libraries, and
|
||||
programming languages may use the term
|
||||
<span class="emphasis"><em>thread-safe</em></span> for data structures or objects
|
||||
that have this characteristic. The two terms mean the
|
||||
same thing.
|
||||
</p>
|
||||
<p>
|
||||
For a description of free-threaded DB objects, see
|
||||
<a href="txnconcurrency.html#concurrenthandles">Which DB Handles are Free-Threaded</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="emphasis"><em>Blocked</em></span>
|
||||
</p>
|
||||
<p>
|
||||
When a thread cannot obtain a lock because some other
|
||||
thread already holds a lock on that object, the lock
|
||||
attempt is said to be <span class="emphasis"><em>blocked</em></span>. See
|
||||
<a href="blocking_deadlocks.html#blocks">Blocks</a> for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span class="emphasis"><em>Deadlock</em></span>
|
||||
</p>
|
||||
<p>
|
||||
Occurs when two or more threads of control attempt to access conflicting resource in such a way as none
|
||||
of the threads can any longer may further progress.
|
||||
</p>
|
||||
<p>
|
||||
For example, if Thread A is blocked waiting for a resource held by Thread
|
||||
B, while at the same time Thread B is blocked waiting for a
|
||||
resource held by Thread A, then neither thread can make any
|
||||
forward progress. In this situation, Thread A and Thread B
|
||||
are said to be <span class="emphasis"><em>deadlocked.</em></span>
|
||||
</p>
|
||||
<p>
|
||||
For more information, see <a href="blocking_deadlocks.html#deadlocks">Deadlocks</a>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="concurrenthandles"></a>Which DB Handles are Free-Threaded</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The following describes to what extent and under what conditions
|
||||
individual handles are free-threaded.
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<tt class="classname">Environment</tt>
|
||||
</p>
|
||||
<p>
|
||||
Free-threaded so long as
|
||||
|
||||
<span>
|
||||
<tt class="methodname">EnvironmentConfig.setThreaded()</tt>
|
||||
is set to <tt class="literal">true</tt>.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<tt class="classname">Database</tt>
|
||||
</p>
|
||||
<p>
|
||||
Free-threaded so long as
|
||||
|
||||
<span>
|
||||
the database is opened in a free-threaded environment.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="classname">SecondaryDatabase</tt>
|
||||
</p>
|
||||
<p>
|
||||
Same conditions apply as for <tt class="classname">Database</tt>
|
||||
handles.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<tt class="classname">Cursor</tt>
|
||||
</p>
|
||||
<p>
|
||||
Cursors are not free-threaded. However, they
|
||||
can be used by multiple threads of control so
|
||||
long as the application serializes access to the handle.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="classname">SecondaryCursor</tt>
|
||||
</p>
|
||||
<p>
|
||||
Same conditions apply as for <tt class="classname">Cursor</tt>
|
||||
handles.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
<tt class="classname">Transaction</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Access must be serialized by the application across threads of control.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
All classes found in the DPL (<tt class="literal">com.sleepycat.persist.*</tt>) are free-threaded.
|
||||
</p>
|
||||
<p>
|
||||
All classes found in the bind APIs (<tt class="literal">com.sleepycat.bind.*</tt>) are free-threaded.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="maxtxns.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="blocking_deadlocks.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Configuring the Transaction Subsystem </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Locks, Blocks, and Deadlocks</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
211
docs/gsg_txn/JAVA/txncursor.html
Normal file
211
docs/gsg_txn/JAVA/txncursor.html
Normal file
@@ -0,0 +1,211 @@
|
||||
<?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</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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="nestedtxn.html" title="Nested Transactions" />
|
||||
<link rel="next" href="txnindices.html" title="Secondary Indices with Transaction Applications" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Transactional Cursors</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="nestedtxn.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnindices.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="txncursor"></a>Transactional Cursors</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You can transaction-protect your cursor operations by
|
||||
specifying a transaction handle at the time that you create
|
||||
your cursor. Beyond that, you do not ever
|
||||
provide a transaction handle directly to a cursor method.
|
||||
</p>
|
||||
<p>
|
||||
Note that if you transaction-protect a cursor, then you must
|
||||
make sure that the cursor is closed before you either commit or
|
||||
abort the transaction. For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
|
||||
// Database and environment opens omitted
|
||||
|
||||
String replacementData = "new data";
|
||||
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
// Use the transaction handle here
|
||||
cursor = db.openCursor(txn, null);
|
||||
DatabaseEntry key, data;
|
||||
|
||||
DatabaseEntry key, data;
|
||||
while(cursor.getNext(key, data, LockMode.DEFAULT) ==
|
||||
OperationStatus.SUCCESS) {
|
||||
|
||||
data.setData(replacementData.getBytes("UTF-8"));
|
||||
// No transaction handle is used on the cursor read or write
|
||||
// methods.
|
||||
cursor.putCurrent(data);
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
cursor = null;
|
||||
txn.commit();
|
||||
txn = null;
|
||||
} catch (Exception e) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
if (txn != null) {
|
||||
txn.abort();
|
||||
txn = null;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} </pre>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="dplcursors"></a>Using Transactional DPL Cursors</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
When using the DPL, you create the cursor using the entity
|
||||
class's primary or secondary index (see the
|
||||
|
||||
<i class="citetitle">Getting Started with Berkeley DB for Java</i>
|
||||
guide for details). At the time that you create the cursor, you
|
||||
pass a transaction handle to the <tt class="methodname">entities()</tt>
|
||||
method, and this causes all subsequent operations performed
|
||||
using that cursor to be performed within the scope of the
|
||||
transaction.
|
||||
</p>
|
||||
<p>
|
||||
Note that if you are using a transaction-enabled store,
|
||||
then you must provide a transaction handle when you open
|
||||
your cursor.
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import com.sleepycat.persist.EntityCursor;
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.PrimaryIndex;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
EntityStore store = null;
|
||||
|
||||
...
|
||||
|
||||
|
||||
// Store and environment open omitted, as is the DataAccessor
|
||||
// instantiation.
|
||||
|
||||
...
|
||||
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
PrimaryIndex<String,Inventory> pi =
|
||||
store.getPrimaryIndex(String.class, Inventory.class);
|
||||
EntityCursor<Inventory> pi_cursor = pi.entities(txn, null);
|
||||
|
||||
try {
|
||||
for (Inventory ii : pi_cursor) {
|
||||
// do something with each object "ii"
|
||||
// A transactional handle is not required for any write operations.
|
||||
// All operations performed using this cursor will be done within
|
||||
// the scope of the transaction, txn.
|
||||
}
|
||||
pi_cursor.close();
|
||||
pi_cursor = null;
|
||||
txn.commit();
|
||||
txn = null;
|
||||
// Always make sure the cursor is closed when we are done with it.
|
||||
} catch (Exception e) {
|
||||
if (pi_cursor != null) {
|
||||
pi_cursor.close();
|
||||
}
|
||||
if (txn != null) {
|
||||
txn.abort();
|
||||
txn = null;
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="nestedtxn.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txnindices.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Nested Transactions </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Secondary Indices with Transaction Applications</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
739
docs/gsg_txn/JAVA/txnexample_dpl.html
Normal file
739
docs/gsg_txn/JAVA/txnexample_dpl.html
Normal file
@@ -0,0 +1,739 @@
|
||||
<?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>DPL Transaction Example</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="wrapup.html" title="Chapter 6. Summary and Examples" />
|
||||
<link rel="previous" href="txnexample_java.html" title="Base API Transaction Example" />
|
||||
<link rel="next" href="inmem_txnexample_java.html" title="Base API In-Memory Transaction Example" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">DPL Transaction Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txnexample_java.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 6. Summary and Examples</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="inmem_txnexample_java.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="txnexample_dpl"></a>DPL Transaction Example</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The following Java code provides a fully functional example of a
|
||||
multi-threaded transactional DB application using the DPL.
|
||||
This example is nearly identical to the example provided in the
|
||||
previous section, except that it uses an entity class and entity
|
||||
store to manage its data.
|
||||
</p>
|
||||
<p>
|
||||
As is the case with the previous examples, this example opens
|
||||
an environment and then an entity store. It then creates
|
||||
5 threads, each of which writes 500 records to the database.
|
||||
The primary key for these writes are based on pre-determined
|
||||
integers, while the data is randomly generated data.
|
||||
This means that the actual data is arbitrary and therefore uninteresting;
|
||||
we picked it only because it requires minimum code to implement and therefore will
|
||||
stay out of the way of the main points of this example.
|
||||
</p>
|
||||
<p>
|
||||
Each thread writes 10 records under a single transaction
|
||||
before committing and writing another 10 (this is repeated 50
|
||||
times). At the end of each transaction, but before committing, each
|
||||
thread calls a function that uses a cursor to read every record in
|
||||
the database. We do this in order to make some points about
|
||||
database reads in a transactional environment.
|
||||
</p>
|
||||
<p>
|
||||
Of course, each writer thread performs deadlock detection as
|
||||
described in this manual. In addition, normal recovery is performed
|
||||
when the environment is opened.
|
||||
</p>
|
||||
<p>
|
||||
To implement this example, we need three classes:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">TxnGuide.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This is the main class for the application. It performs
|
||||
environment and store management, spawns threads, and
|
||||
creates the data that is placed in the database. See <a href="txnexample_dpl.html#txnguideexample_dpl">TxnGuide.java</a> for implementation details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">StoreWriter.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This class extends <tt class="literal">java.lang.Thread</tt>, and
|
||||
as such it is our thread implementation. It is responsible
|
||||
for actually reading and writing store. It also
|
||||
performs all of our transaction management. See <a href="txnexample_dpl.html#storewriter">StoreWriter.java</a> for
|
||||
implementation details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">PayloadDataEntity.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This is an entity class used to encapsulate several data
|
||||
fields. See <a href="txnexample_dpl.html#payloaddataentity">PayloadDataEntity.java</a> for
|
||||
implementation details.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="txnguideexample_dpl"></a>TxnGuide.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The main class in our example application is used to open and
|
||||
close our environment and store. It also spawns all the
|
||||
threads that we need. We start with the normal series
|
||||
of Java package and import statements, followed by our class
|
||||
declaration:
|
||||
</p>
|
||||
<pre class="programlisting">// File TxnGuideDPL.java
|
||||
|
||||
package persist.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.LockDetectMode;
|
||||
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.StoreConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public class TxnGuideDPL { </pre>
|
||||
<p>
|
||||
Next we declare our class' private data members. Mostly these are used
|
||||
for constants such as the name of the database that we are opening and
|
||||
the number of threads that we are spawning. However, we also declare
|
||||
our environment and database handles here.
|
||||
</p>
|
||||
<pre class="programlisting"> private static String myEnvPath = "./";
|
||||
private static String storeName = "exampleStore";
|
||||
|
||||
// Handles
|
||||
private static EntityStore myStore = null;
|
||||
private static Environment myEnv = null;
|
||||
private static final int NUMTHREADS = 5; </pre>
|
||||
<p>
|
||||
Next, we implement our <tt class="function">usage()</tt> method. This
|
||||
application optionally accepts a single command line argument which is
|
||||
used to identify the environment home directory.
|
||||
</p>
|
||||
<pre class="programlisting"> private static void usage() {
|
||||
System.out.println("TxnGuideDPL [-h <env directory>]");
|
||||
System.exit(-1);
|
||||
} </pre>
|
||||
<p>
|
||||
Now we implement our <tt class="function">main()</tt> method. This method
|
||||
simply calls the methods to parse the command line arguments and open
|
||||
the environment and store. It also creates and then joins the store writer
|
||||
threads.
|
||||
</p>
|
||||
<pre class="programlisting"> public static void main(String args[]) {
|
||||
try {
|
||||
// Parse the arguments list
|
||||
parseArgs(args);
|
||||
// Open the environment and store
|
||||
openEnv();
|
||||
|
||||
// Start the threads
|
||||
StoreWriter[] threadArray;
|
||||
threadArray = new StoreWriter[NUMTHREADS];
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i] = new StoreWriter(myEnv, myStore);
|
||||
threadArray[i].start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i].join();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("TxnGuideDPL: " + e.toString());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
closeEnv();
|
||||
}
|
||||
System.out.println("All done.");
|
||||
} </pre>
|
||||
<p>
|
||||
Next we implement <tt class="function">openEnv()</tt>. This method is used
|
||||
to open the environment and then an entity store in that environment. Along
|
||||
the way, we make sure that every handle is free-threaded, and that the
|
||||
transactional subsystem is correctly initialized. Because this is a
|
||||
concurrent application, we also declare how we want deadlock detection
|
||||
to be performed. In this case, we use DB's internal block detector
|
||||
to determine whether a deadlock has occurred when a thread attempts to
|
||||
acquire a lock. We also indicate that we want the deadlocked thread
|
||||
with the <span class="emphasis"><em>youngest</em></span> lock to receive deadlock
|
||||
notification.
|
||||
</p>
|
||||
<p>
|
||||
Notice that we also cause normal recovery to be run when we open the
|
||||
environment. This is the standard and recommended thing to do whenever
|
||||
you start up a transactional application.
|
||||
</p>
|
||||
<p>
|
||||
Finally, notice that we open the database such that it supports
|
||||
uncommitted reads. We do this so that some cursor activity later in
|
||||
this example can read uncommitted data. If we did not do this, then
|
||||
our <tt class="methodname">countObjects()</tt> method described later in
|
||||
this example would cause our thread to self-deadlock. This is because
|
||||
the cursor could not be opened to support uncommitted reads (that flag
|
||||
on the cursor open would, in fact, be silently ignored).
|
||||
</p>
|
||||
<pre class="programlisting"> private static void openEnv() throws DatabaseException {
|
||||
System.out.println("opening env and store");
|
||||
|
||||
// Set up the environment.
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setAllowCreate(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setRunRecovery(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
// EnvironmentConfig.setThreaded(true) is the default behavior
|
||||
// in Java, so we do not have to do anything to cause the
|
||||
// environment handle to be free-threaded.
|
||||
|
||||
// Indicate that we want db to internally perform deadlock
|
||||
// detection. Also indicate that the transaction that has
|
||||
// performed the least amount of write activity to
|
||||
// receive the deadlock notification, if any.
|
||||
myEnvConfig.setLockDetectMode(LockDetectMode.MINWRITE);
|
||||
|
||||
// Set up the entity store
|
||||
StoreConfig myStoreConfig = new StoreConfig();
|
||||
myStoreConfig.setAllowCreate(true);
|
||||
myStoreConfig.setTransactional(true);
|
||||
|
||||
// Need a DatabaseConfig object so as to set uncommitted read
|
||||
// support.
|
||||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||||
myDbConfig.setType(DatabaseType.BTREE);
|
||||
myDbConfig.setAllowCreate(true);
|
||||
myDbConfig.setTransactional(true);
|
||||
myDbConfig.setReadUncommitted(true);
|
||||
|
||||
try {
|
||||
// Open the environment
|
||||
myEnv = new Environment(new File(myEnvPath), // Env home
|
||||
myEnvConfig);
|
||||
|
||||
// Open the store
|
||||
myStore = new EntityStore(myEnv, storeName, myStoreConfig);
|
||||
|
||||
// Set the DatabaseConfig object, so that the underlying
|
||||
// database is configured for uncommitted reads.
|
||||
myStore.setPrimaryConfig(PayloadDataEntity.class, myDbConfig);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
System.err.println("openEnv: " + fnfe.toString());
|
||||
System.exit(-1);
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Finally, we implement the methods used to close our environment and
|
||||
databases, parse the command line arguments, and provide our class
|
||||
constructor. This is fairly standard code and it is mostly
|
||||
uninteresting from the perspective of this manual. We include it here
|
||||
purely for the purpose of completeness.
|
||||
</p>
|
||||
<pre class="programlisting"> private static void closeEnv() {
|
||||
System.out.println("Closing env and store");
|
||||
if (myStore != null ) {
|
||||
try {
|
||||
myStore.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: myStore: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (myEnv != null ) {
|
||||
try {
|
||||
myEnv.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TxnGuideDPL() {}
|
||||
|
||||
private static void parseArgs(String args[]) {
|
||||
int nArgs = args.length;
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
if (args[i].startsWith("-")) {
|
||||
switch(args[i].charAt(1)) {
|
||||
case 'h':
|
||||
if (i < nArgs - 1) {
|
||||
myEnvPath = new String(args[++i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="payloaddataentity"></a>PayloadDataEntity.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before we show the implementation of the store writer thread, we
|
||||
need to show the class that we will be placing into the store. This
|
||||
class is fairly minimal. It simply allows you to store and retrieve an
|
||||
<tt class="literal">int</tt>, a <tt class="literal">String</tt>, and a
|
||||
<tt class="literal">double</tt>. The <tt class="literal">int</tt> is our primary key.
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
import com.sleepycat.persist.model.Entity;
|
||||
import com.sleepycat.persist.model.PrimaryKey;
|
||||
import static com.sleepycat.persist.model.Relationship.*;
|
||||
|
||||
@Entity
|
||||
public class PayloadDataEntity {
|
||||
@PrimaryKey
|
||||
private int oID;
|
||||
|
||||
private String threadName;
|
||||
|
||||
private double doubleData;
|
||||
|
||||
PayloadDataEntity() {}
|
||||
|
||||
public double getDoubleData() { return doubleData; }
|
||||
public int getID() { return oID; }
|
||||
public String getThreadName() { return threadName; }
|
||||
|
||||
public void setDoubleData(double dd) { doubleData = dd; }
|
||||
public void setID(int id) { oID = id; }
|
||||
public void setThreadName(String tn) { threadName = tn; }
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="storewriter"></a>StoreWriter.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
<tt class="literal">StoreWriter.java</tt> provides the implementation
|
||||
for our entity store writer thread. It is responsible for:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
All transaction management.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Responding to deadlock exceptions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Providing data to be stored in the entity store.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Writing the data to the store.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
In order to show off some of the ACID properties provided
|
||||
by DB's transactional support,
|
||||
<tt class="literal">StoreWriter.java</tt> does some things in a less
|
||||
efficient way than you would probably decide to use in a
|
||||
true production application. First, it groups 10 database
|
||||
writes together in a single transaction when you could just
|
||||
as easily perform one write for each transaction. If you
|
||||
did this, you could use auto commit for the individual
|
||||
database writes, which means your code would be slightly
|
||||
simpler and you would run a <span class="emphasis"><em>much</em></span>
|
||||
smaller chance of encountering blocked and deadlocked
|
||||
operations. However, by doing things this way, we are able
|
||||
to show transactional atomicity, as well as deadlock
|
||||
handling.
|
||||
</p>
|
||||
<p>
|
||||
To begin, we provide the usual package and import statements, and we declare our class:
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
|
||||
import com.sleepycat.db.CursorConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DeadlockException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import com.sleepycat.persist.EntityCursor;
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.PrimaryIndex;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class StoreWriter extends Thread
|
||||
{ </pre>
|
||||
<p>
|
||||
Next we declare our private data members. Notice that we get handles
|
||||
for the environment and the entity store. The random number generator
|
||||
that we instantiate is used
|
||||
to generate unique data for storage in the database. Finally, the
|
||||
<tt class="literal">MAX_RETRY</tt> variable is used to define how many times
|
||||
we will retry a transaction in the face of a deadlock.
|
||||
</p>
|
||||
<pre class="programlisting"> private EntityStore myStore = null;
|
||||
private Environment myEnv = null;
|
||||
private PrimaryIndex<Integer,PayloadDataEntity> pdKey;
|
||||
private Random generator = new Random();
|
||||
private boolean passTxn = false;
|
||||
|
||||
private static final int MAX_RETRY = 20; </pre>
|
||||
<p>
|
||||
Next we implement our class constructor. The most interesting thing about our constructor is
|
||||
that we use it to obtain our entity class's primary index.
|
||||
</p>
|
||||
<pre class="programlisting"> // Constructor. Get our handles from here
|
||||
StoreWriter(Environment env, EntityStore store)
|
||||
|
||||
throws DatabaseException {
|
||||
myStore = store;
|
||||
myEnv = env;
|
||||
|
||||
// Open the data accessor. This is used to store persistent
|
||||
// objects.
|
||||
pdKey = myStore.getPrimaryIndex(Integer.class,
|
||||
PayloadDataEntity.class);
|
||||
} </pre>
|
||||
<p>
|
||||
Now we implement our thread's <tt class="methodname">run()</tt> method.
|
||||
This is the method that is run when <tt class="classname">StoreWriter</tt>
|
||||
threads are started in the main program (see <a href="txnexample_dpl.html#txnguideexample_dpl">TxnGuide.java</a>).
|
||||
</p>
|
||||
<pre class="programlisting"> // Thread method that writes a series of records
|
||||
// to the database using transaction protection.
|
||||
// Deadlock handling is demonstrated here.
|
||||
public void run () { </pre>
|
||||
<p>
|
||||
The first thing we do is get a <tt class="literal">null</tt> transaction
|
||||
handle before going into our main loop. We also begin the top transaction loop here that causes our application to
|
||||
perform 50 transactions.
|
||||
</p>
|
||||
<pre class="programlisting"> Transaction txn = null;
|
||||
|
||||
// Perform 50 transactions
|
||||
for (int i=0; i<50; i++) { </pre>
|
||||
<p>
|
||||
Next we declare a <tt class="literal">retry</tt> variable. This is used to
|
||||
determine whether a deadlock should result in our retrying the
|
||||
operation. We also declare a <tt class="literal">retry_count</tt> variable
|
||||
that is used to make sure we do not retry a transaction forever in the
|
||||
unlikely event that the thread is unable to ever get a necessary lock.
|
||||
(The only thing that might cause this is if some other thread dies
|
||||
while holding an important lock. This is the only code that we have to
|
||||
guard against that because the simplicity of this application makes it
|
||||
highly unlikely that it will ever occur.)
|
||||
</p>
|
||||
<pre class="programlisting"> boolean retry = true;
|
||||
int retry_count = 0;
|
||||
// while loop is used for deadlock retries
|
||||
while (retry) { </pre>
|
||||
<p>
|
||||
Now we go into the <tt class="literal">try</tt> block that we use for
|
||||
deadlock detection. We also begin our transaction here.
|
||||
</p>
|
||||
<pre class="programlisting"> // try block used for deadlock detection and
|
||||
// general exception handling
|
||||
try {
|
||||
|
||||
// Get a transaction
|
||||
txn = myEnv.beginTransaction(null, null); </pre>
|
||||
<p>
|
||||
Now we write 10 objects under the transaction that we have just begun.
|
||||
By combining multiple writes together under a single transaction,
|
||||
we increase the likelihood that a deadlock will occur. Normally,
|
||||
you want to reduce the potential for a deadlock and in this case
|
||||
the way to do that is to perform a single write per transaction. In
|
||||
other words, we <span class="emphasis"><em>should</em></span> be using auto commit to
|
||||
write to our database for this workload.
|
||||
</p>
|
||||
<p>
|
||||
However, we want to show deadlock handling and by performing
|
||||
multiple writes per transaction we can actually observe deadlocks
|
||||
occurring. We also want to underscore the idea that you can
|
||||
combing multiple database operations together in a single atomic
|
||||
unit of work. So for our example, we do the (slightly) wrong thing.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
|
||||
// Write 10 PayloadDataEntity objects to the
|
||||
// store for each transaction
|
||||
for (int j = 0; j < 10; j++) {
|
||||
// Instantiate an object
|
||||
PayloadDataEntity pd = new PayloadDataEntity();
|
||||
|
||||
// Set the Object ID. This is used as the
|
||||
// primary key.
|
||||
pd.setID(i + j);
|
||||
|
||||
// The thread name is used as a secondary key, and
|
||||
// it is retrieved by this class's getName()
|
||||
// method.
|
||||
pd.setThreadName(getName());
|
||||
|
||||
// The last bit of data that we use is a double
|
||||
// that we generate randomly. This data is not
|
||||
// indexed.
|
||||
pd.setDoubleData(generator.nextDouble());
|
||||
|
||||
// Do the put
|
||||
pdKey.put(txn, pd);
|
||||
} </pre>
|
||||
<p>
|
||||
Having completed the inner database write loop, we could simply
|
||||
commit the transaction and continue on to the next block of 10
|
||||
writes. However, we want to first illustrate a few points about
|
||||
transactional processing so instead we call our
|
||||
<tt class="function">countObjects()</tt> method before calling the transaction
|
||||
commit. <tt class="function">countObjects()</tt> uses a cursor to read every
|
||||
object in the entity store and return a count of the number of objects
|
||||
that it found.
|
||||
</p>
|
||||
<p>
|
||||
Because
|
||||
<tt class="function">countObjects()</tt>
|
||||
reads every object in the store, if used incorrectly the thread
|
||||
will self-deadlock. The writer thread has just written 500 objects
|
||||
to the database, but because the transaction used for that write
|
||||
has not yet been committed, each of those 500 objects are still
|
||||
locked by the thread's transaction. If we then simply run a
|
||||
non-transactional cursor over the store from within the same
|
||||
thread that has locked those 500 objects, the cursor will
|
||||
block when it tries to read one of those transactional
|
||||
protected records. The thread immediately stops operation at that
|
||||
point while the cursor waits for the read lock it has
|
||||
requested. Because that read lock will never be released (the thread
|
||||
can never make any forward progress), this represents a
|
||||
self-deadlock for the thread.
|
||||
</p>
|
||||
<p>
|
||||
There are three ways to prevent this self-deadlock:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
We can move the call to
|
||||
<tt class="function">countObjects()</tt> to a point after the
|
||||
thread's transaction has committed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
We can allow <tt class="function">countObjects()</tt> to
|
||||
operate under the same transaction as all of the writes
|
||||
were performed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
We can reduce our isolation guarantee for the application
|
||||
by allowing uncommitted reads.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
For this example, we choose to use option 3 (uncommitted reads) to avoid
|
||||
the deadlock. This means that we have to open our underlying database such
|
||||
that it supports uncommitted reads, and we have to open our cursor handle
|
||||
so that it knows to perform uncommitted reads.
|
||||
</p>
|
||||
<pre class="programlisting"> // commit
|
||||
System.out.println(getName() + " : committing txn : " + i);
|
||||
System.out.println(getName() + " : Found " +
|
||||
countObjects(txn) + " objects in the store."); </pre>
|
||||
<p>
|
||||
Having performed this somewhat inelegant counting of the objects in the
|
||||
database, we can now commit the transaction.
|
||||
</p>
|
||||
<pre class="programlisting"> try {
|
||||
txn.commit();
|
||||
txn = null;
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("Error on txn commit: " +
|
||||
e.toString());
|
||||
}
|
||||
retry = false; </pre>
|
||||
<p>
|
||||
If all goes well with the commit, we are done and we can move on to the
|
||||
next batch of 10 objects to add to the store. However, in the event
|
||||
of an error, we must handle our exceptions correctly. The first of
|
||||
these is a deadlock exception. In the event of a deadlock, we want to
|
||||
abort and retry the transaction, provided that we have not already
|
||||
exceeded our retry limit for this transaction.
|
||||
</p>
|
||||
<pre class="programlisting"> } catch (DeadlockException de) {
|
||||
System.out.println("################# " + getName() +
|
||||
" : caught deadlock");
|
||||
// retry if necessary
|
||||
if (retry_count < MAX_RETRY) {
|
||||
System.err.println(getName() +
|
||||
" : Retrying operation.");
|
||||
retry = true;
|
||||
retry_count++;
|
||||
} else {
|
||||
System.err.println(getName() +
|
||||
" : out of retries. Giving up.");
|
||||
retry = false;
|
||||
} </pre>
|
||||
<p>
|
||||
In the event of a standard, non-specific database exception, we simply
|
||||
log the exception and then give up (the transaction is not retried).
|
||||
</p>
|
||||
<pre class="programlisting"> } catch (DatabaseException e) {
|
||||
// abort and don't retry
|
||||
retry = false;
|
||||
System.err.println(getName() +
|
||||
" : caught exception: " + e.toString());
|
||||
System.err.println(getName() +
|
||||
" : errno: " + e.getErrno());
|
||||
e.printStackTrace(); </pre>
|
||||
<p>
|
||||
And, finally, we always abort the transaction if the transaction handle
|
||||
is not null. Note that immediately after committing our transaction, we
|
||||
set the transaction handle to null to guard against aborting a
|
||||
transaction that has already been committed.
|
||||
</p>
|
||||
<pre class="programlisting"> } finally {
|
||||
if (txn != null) {
|
||||
try {
|
||||
txn.abort();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error aborting txn: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
The final piece of our <tt class="classname">StoreWriter</tt> class is the
|
||||
<tt class="methodname">countObjects()</tt> implementation. Notice how in
|
||||
this example we open the cursor such that it performs uncommitted
|
||||
reads:
|
||||
</p>
|
||||
<pre class="programlisting"> // A method that counts every object in the store.
|
||||
|
||||
private int countObjects(Transaction txn) throws DatabaseException {
|
||||
int count = 0;
|
||||
|
||||
CursorConfig cc = new CursorConfig();
|
||||
// This is ignored if the store is not opened with uncommitted read
|
||||
// support.
|
||||
cc.setReadUncommitted(true);
|
||||
EntityCursor<PayloadDataEntity> cursor = pdKey.entities(txn, cc);
|
||||
|
||||
try {
|
||||
for (PayloadDataEntity pdi : cursor) {
|
||||
count++;
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
<p>
|
||||
This completes our transactional example. If you would like to
|
||||
experiment with this code, you can find the example in the following
|
||||
location in your DB distribution:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_java/src/persist/txn</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txnexample_java.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="wrapup.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="inmem_txnexample_java.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Base API Transaction Example </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Base API In-Memory Transaction Example</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
801
docs/gsg_txn/JAVA/txnexample_java.html
Normal file
801
docs/gsg_txn/JAVA/txnexample_java.html
Normal file
@@ -0,0 +1,801 @@
|
||||
<?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>Base API Transaction Example</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="wrapup.html" title="Chapter 6. Summary and Examples" />
|
||||
<link rel="previous" href="wrapup.html" title="Chapter 6. Summary and Examples" />
|
||||
<link rel="next" href="txnexample_dpl.html" title="DPL Transaction Example" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Base API Transaction Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="wrapup.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 6. Summary and Examples</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnexample_dpl.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="txnexample_java"></a>Base API Transaction Example</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The following Java code provides a fully functional example of a
|
||||
multi-threaded transactional DB application.
|
||||
The example opens an environment and database, and then creates 5
|
||||
threads, each of which writes 500 records to the database. The keys
|
||||
used for these writes are pre-determined strings, while the data is
|
||||
a class that contains randomly generated data. This means that the actual
|
||||
data is arbitrary and therefore uninteresting; we picked it only
|
||||
because it requires minimum code to implement and therefore will
|
||||
stay out of the way of the main points of this example.
|
||||
</p>
|
||||
<p>
|
||||
Each thread writes 10 records under a single transaction
|
||||
before committing and writing another 10 (this is repeated 50
|
||||
times). At the end of each transaction, but before committing, each
|
||||
thread calls a function that uses a cursor to read every record in
|
||||
the database. We do this in order to make some points about
|
||||
database reads in a transactional environment.
|
||||
</p>
|
||||
<p>
|
||||
Of course, each writer thread performs deadlock detection as
|
||||
described in this manual. In addition, normal recovery is performed
|
||||
when the environment is opened.
|
||||
</p>
|
||||
<p>
|
||||
To implement this example, we need three classes:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">TxnGuide.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This is the main class for the application. It performs
|
||||
environment and database management, spawns threads, and
|
||||
creates the data that is placed in the database. See <a href="txnexample_java.html#txnguideexample">TxnGuide.java</a> for implementation details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">DBWriter.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This class extends <tt class="literal">java.lang.Thread</tt>, and
|
||||
as such it is our thread implementation. It is responsible
|
||||
for actually reading and writing to the database. It also
|
||||
performs all of our transaction management. See <a href="txnexample_java.html#dbwriter">DBWriter.java</a> for
|
||||
implementation details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="literal">PayloadData.java</tt>
|
||||
</p>
|
||||
<p>
|
||||
This is a data class used to encapsulate several data
|
||||
fields. It is fairly uninteresting, except that the usage
|
||||
of a class means that we have to use the bind APIs to
|
||||
serialize it for storage in the database. See <a href="txnexample_java.html#payloaddata">PayloadData.java</a> for
|
||||
implementation details.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="txnguideexample"></a>TxnGuide.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
The main class in our example application is used to open and
|
||||
close our environment and database. It also spawns all the
|
||||
threads that we need. We start with the normal series
|
||||
of Java package and import statements, followed by our class
|
||||
declaration:
|
||||
</p>
|
||||
<pre class="programlisting">// File TxnGuide.java
|
||||
|
||||
package db.txn;
|
||||
|
||||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.LockDetectMode;
|
||||
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public class TxnGuide { </pre>
|
||||
<p>
|
||||
Next we declare our class' private data members. Mostly these are used
|
||||
for constants such as the name of the database that we are opening and
|
||||
the number of threads that we are spawning. However, we also declare
|
||||
our environment and database handles here.
|
||||
</p>
|
||||
<pre class="programlisting"> private static String myEnvPath = "./";
|
||||
private static String dbName = "mydb.db";
|
||||
private static String cdbName = "myclassdb.db";
|
||||
|
||||
// DB handles
|
||||
private static Database myDb = null;
|
||||
private static Database myClassDb = null;
|
||||
private static Environment myEnv = null;
|
||||
|
||||
private static final int NUMTHREADS = 5; </pre>
|
||||
<p>
|
||||
Next, we implement our <tt class="function">usage()</tt> method. This
|
||||
application optionally accepts a single command line argument which is
|
||||
used to identify the environment home directory.
|
||||
</p>
|
||||
<pre class="programlisting"> private static void usage() {
|
||||
System.out.println("TxnGuide [-h <env directory>]");
|
||||
System.exit(-1);
|
||||
} </pre>
|
||||
<p>
|
||||
Now we implement our <tt class="function">main()</tt> method. This method
|
||||
simply calls the methods to parse the command line arguments and open
|
||||
the environment and database. It also creates the stored class catalog
|
||||
that we use for serializing the data that we want to store in our
|
||||
database. Finally, it creates and then joins the database writer
|
||||
threads.
|
||||
</p>
|
||||
<pre class="programlisting"> public static void main(String args[]) {
|
||||
try {
|
||||
// Parse the arguments list
|
||||
parseArgs(args);
|
||||
// Open the environment and databases
|
||||
openEnv();
|
||||
// Get our class catalog (used to serialize objects)
|
||||
StoredClassCatalog classCatalog =
|
||||
new StoredClassCatalog(myClassDb);
|
||||
|
||||
// Start the threads
|
||||
DBWriter[] threadArray;
|
||||
threadArray = new DBWriter[NUMTHREADS];
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i] = new DBWriter(myEnv, myDb, classCatalog);
|
||||
threadArray[i].start();
|
||||
}
|
||||
|
||||
// Join the threads. That is, wait for each thread to
|
||||
// complete before exiting the application.
|
||||
for (int i = 0; i < NUMTHREADS; i++) {
|
||||
threadArray[i].join();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("TxnGuide: " + e.toString());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
closeEnv();
|
||||
}
|
||||
System.out.println("All done.");
|
||||
} </pre>
|
||||
<p>
|
||||
Next we implement <tt class="function">openEnv()</tt>. This method is used
|
||||
to open the environment and then a database in that environment. Along
|
||||
the way, we make sure that every handle is free-threaded, and that the
|
||||
transactional subsystem is correctly initialized. Because this is a
|
||||
concurrent application, we also declare how we want deadlock detection
|
||||
to be performed. In this case, we use DB's internal block detector
|
||||
to determine whether a deadlock has occurred when a thread attempts to
|
||||
acquire a lock. We also indicate that we want the deadlocked thread
|
||||
with the <span class="emphasis"><em>youngest</em></span> lock to receive deadlock
|
||||
notification.
|
||||
</p>
|
||||
<p>
|
||||
Notice that we also cause normal recovery to be run when we open the
|
||||
environment. This is the standard and recommended thing to do whenever
|
||||
you start up a transactional application.
|
||||
</p>
|
||||
<p>
|
||||
For the database open, notice that we open the database such that it
|
||||
supports duplicate records. This is required purely by the data that
|
||||
we are writing to the database, and it is only necessary if you run the
|
||||
application more than once without first deleting the environment.
|
||||
</p>
|
||||
<p>
|
||||
Finally, notice that we open the database such that it supports
|
||||
uncommitted reads. We do this so that some cursor activity later in
|
||||
this example can read uncommitted data. If we did not do this, then
|
||||
our <tt class="methodname">countRecords()</tt> method described later in
|
||||
this example would cause our thread to self-deadlock. This is because
|
||||
the cursor could not be opened to support uncommitted reads (that flag
|
||||
on the cursor open would, in fact, be silently ignored).
|
||||
</p>
|
||||
<pre class="programlisting"> private static void openEnv() throws DatabaseException {
|
||||
System.out.println("opening env");
|
||||
|
||||
// Set up the environment.
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setAllowCreate(true);
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setRunRecovery(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
// EnvironmentConfig.setThreaded(true) is the default behavior
|
||||
// in Java, so we do not have to do anything to cause the
|
||||
// environment handle to be free-threaded.
|
||||
|
||||
// Indicate that we want db to internally perform deadlock
|
||||
// detection. Also indicate that the transaction that has
|
||||
// performed the least amount of write activity to
|
||||
// receive the deadlock notification, if any.
|
||||
myEnvConfig.setLockDetectMode(LockDetectMode.MINWRITE);
|
||||
|
||||
// Set up the database
|
||||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||||
myDbConfig.setType(DatabaseType.BTREE);
|
||||
myDbConfig.setAllowCreate(true);
|
||||
myDbConfig.setTransactional(true);
|
||||
myDbConfig.setSortedDuplicates(true);
|
||||
myDbConfig.setReadUncomitted(true);
|
||||
// no DatabaseConfig.setThreaded() method available.
|
||||
// db handles in java are free-threaded so long as the
|
||||
// env is also free-threaded.
|
||||
|
||||
try {
|
||||
// Open the environment
|
||||
myEnv = new Environment(new File(myEnvPath), // Env home
|
||||
myEnvConfig);
|
||||
|
||||
// Open the database. Do not provide a txn handle. This open
|
||||
// is auto committed because DatabaseConfig.setTransactional()
|
||||
// is true.
|
||||
myDb = myEnv.openDatabase(null, // txn handle
|
||||
dbName, // Database file name
|
||||
null, // Database name
|
||||
myDbConfig);
|
||||
|
||||
// Used by the bind API for serializing objects
|
||||
// Class database must not support duplicates
|
||||
myDbConfig.setSortedDuplicates(false);
|
||||
myClassDb = myEnv.openDatabase(null, // txn handle
|
||||
cdbName, // Database file name
|
||||
null, // Database name,
|
||||
myDbConfig);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
System.err.println("openEnv: " + fnfe.toString());
|
||||
System.exit(-1);
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
Finally, we implement the methods used to close our environment and
|
||||
databases, parse the command line arguments, and provide our class
|
||||
constructor. This is fairly standard code and it is mostly
|
||||
uninteresting from the perspective of this manual. We include it here
|
||||
purely for the purpose of completeness.
|
||||
</p>
|
||||
<pre class="programlisting"> private static void closeEnv() {
|
||||
System.out.println("Closing env and databases");
|
||||
if (myDb != null ) {
|
||||
try {
|
||||
myDb.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: myDb: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (myClassDb != null ) {
|
||||
try {
|
||||
myClassDb.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: myClassDb: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (myEnv != null ) {
|
||||
try {
|
||||
myEnv.close();
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("closeEnv: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TxnGuide() {}
|
||||
|
||||
private static void parseArgs(String args[]) {
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
if (args[i].startsWith("-")) {
|
||||
switch(args[i].charAt(1)) {
|
||||
case 'h':
|
||||
myEnvPath = new String(args[++i]);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="payloaddata"></a>PayloadData.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Before we show the implementation of the database writer thread, we
|
||||
need to show the class that we will be placing into the database. This
|
||||
class is fairly minimal. It simply allows you to store and retrieve an
|
||||
<tt class="literal">int</tt>, a <tt class="literal">String</tt>, and a
|
||||
<tt class="literal">double</tt>. We will be using the DB bind API from
|
||||
within the writer thread to serialize instances of this class and place
|
||||
them into our database.
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PayloadData implements Serializable {
|
||||
private int oID;
|
||||
private String threadName;
|
||||
private double doubleData;
|
||||
|
||||
PayloadData(int id, String name, double data) {
|
||||
oID = id;
|
||||
threadName = name;
|
||||
doubleData = data;
|
||||
}
|
||||
|
||||
public double getDoubleData() { return doubleData; }
|
||||
public int getID() { return oID; }
|
||||
public String getThreadName() { return threadName; }
|
||||
} </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="dbwriter"></a>DBWriter.java</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
<tt class="literal">DBWriter.java</tt> provides the implementation
|
||||
for our database writer thread. It is responsible for:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
All transaction management.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Responding to deadlock exceptions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Providing data to be stored into the database.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Serializing and then writing the data to the database.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
In order to show off some of the ACID properties provided
|
||||
by DB's transactional support,
|
||||
<tt class="literal">DBWriter.java</tt> does some things in a less
|
||||
efficient way than you would probably decide to use in a
|
||||
true production application. First, it groups 10 database
|
||||
writes together in a single transaction when you could just
|
||||
as easily perform one write for each transaction. If you
|
||||
did this, you could use auto commit for the individual
|
||||
database writes, which means your code would be slightly
|
||||
simpler and you would run a <span class="emphasis"><em>much</em></span>
|
||||
smaller chance of encountering blocked and deadlocked
|
||||
operations. However, by doing things this way, we are able
|
||||
to show transactional atomicity, as well as deadlock
|
||||
handling.
|
||||
</p>
|
||||
<p>
|
||||
At the end of each transaction,
|
||||
<tt class="literal">DBWriter.java</tt> runs a cursor over the
|
||||
entire database by way of counting the number of records
|
||||
currently existing in the database. There are better ways
|
||||
to discover this information, but in this case we want to
|
||||
make some points regarding cursors, transactional
|
||||
applications, and deadlocking (we get into this in more
|
||||
detail later in this section).
|
||||
</p>
|
||||
<p>
|
||||
To begin, we provide the usual package and import statements, and we declare our class:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.bind.EntryBinding;
|
||||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||||
import com.sleepycat.bind.serial.SerialBinding;
|
||||
import com.sleepycat.bind.tuple.StringBinding;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.CursorConfig;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.DeadlockException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Random;
|
||||
|
||||
public class DBWriter extends Thread
|
||||
{ </pre>
|
||||
<p>
|
||||
Next we declare our private data members. Notice that we get handles
|
||||
for the environment and the database. We also obtain a handle for an
|
||||
<tt class="classname">EntryBinding</tt>. We will use this to serialize
|
||||
<tt class="classname">PayloadData</tt> class instances (see <a href="txnexample_java.html#payloaddata">PayloadData.java</a>) for storage in
|
||||
the database. The random number generator that we instantiate is used
|
||||
to generate unique data for storage in the database. The
|
||||
<tt class="literal">MAX_RETRY</tt> variable is used to define how many times
|
||||
we will retry a transaction in the face of a deadlock. And, finally,
|
||||
<tt class="literal">keys</tt> is a <tt class="classname">String</tt> array that
|
||||
holds the keys used for our database entries.
|
||||
</p>
|
||||
<pre class="programlisting"> private Database myDb = null;
|
||||
private Environment myEnv = null;
|
||||
private EntryBinding dataBinding = null;
|
||||
private Random generator = new Random();
|
||||
|
||||
|
||||
private static final int MAX_RETRY = 20;
|
||||
|
||||
private static String[] keys = {"key 1", "key 2", "key 3",
|
||||
"key 4", "key 5", "key 6",
|
||||
"key 7", "key 8", "key 9",
|
||||
"key 10"}; </pre>
|
||||
<p>
|
||||
Next we implement our class constructor. The most interesting thing
|
||||
we do here is instantiate a serial binding for serializing
|
||||
<tt class="classname">PayloadData</tt> instances.
|
||||
</p>
|
||||
<pre class="programlisting"> // Constructor. Get our DB handles from here
|
||||
DBWriter(Environment env, Database db, StoredClassCatalog scc)
|
||||
throws DatabaseException {
|
||||
myDb = db;
|
||||
myEnv = env;
|
||||
dataBinding = new SerialBinding(scc, PayloadData.class);
|
||||
} </pre>
|
||||
<p>
|
||||
Now we implement our thread's <tt class="methodname">run()</tt> method.
|
||||
This is the method that is run when <tt class="classname">DBWriter</tt>
|
||||
threads are started in the main program (see <a href="txnexample_java.html#txnguideexample">TxnGuide.java</a>).
|
||||
</p>
|
||||
<pre class="programlisting"> // Thread method that writes a series of records
|
||||
// to the database using transaction protection.
|
||||
// Deadlock handling is demonstrated here.
|
||||
public void run () { </pre>
|
||||
<p>
|
||||
The first thing we do is get a <tt class="literal">null</tt> transaction
|
||||
handle before going into our main loop. We also begin the top transaction loop here that causes our application to
|
||||
perform 50 transactions.
|
||||
</p>
|
||||
<pre class="programlisting"> Transaction txn = null;
|
||||
|
||||
// Perform 50 transactions
|
||||
for (int i=0; i<50; i++) { </pre>
|
||||
<p>
|
||||
Next we declare a <tt class="literal">retry</tt> variable. This is used to
|
||||
determine whether a deadlock should result in our retrying the
|
||||
operation. We also declare a <tt class="literal">retry_count</tt> variable
|
||||
that is used to make sure we do not retry a transaction forever in the
|
||||
unlikely event that the thread is unable to ever get a necessary lock.
|
||||
(The only thing that might cause this is if some other thread dies
|
||||
while holding an important lock. This is the only code that we have to
|
||||
guard against that because the simplicity of this application makes it
|
||||
highly unlikely that it will ever occur.)
|
||||
</p>
|
||||
<pre class="programlisting"> boolean retry = true;
|
||||
int retry_count = 0;
|
||||
// while loop is used for deadlock retries
|
||||
while (retry) { </pre>
|
||||
<p>
|
||||
Now we go into the <tt class="literal">try</tt> block that we use for
|
||||
deadlock detection. We also begin our transaction here.
|
||||
</p>
|
||||
<pre class="programlisting"> // try block used for deadlock detection and
|
||||
// general db exception handling
|
||||
try {
|
||||
|
||||
// Get a transaction
|
||||
txn = myEnv.beginTransaction(null, null); </pre>
|
||||
<p>
|
||||
Now we write 10 records under the transaction that we have just begun.
|
||||
By combining multiple writes together under a single transaction,
|
||||
we increase the likelihood that a deadlock will occur. Normally,
|
||||
you want to reduce the potential for a deadlock and in this case
|
||||
the way to do that is to perform a single write per transaction. In
|
||||
other words, we <span class="emphasis"><em>should</em></span> be using auto commit to
|
||||
write to our database for this workload.
|
||||
</p>
|
||||
<p>
|
||||
However, we want to show deadlock handling and by performing
|
||||
multiple writes per transaction we can actually observe deadlocks
|
||||
occurring. We also want to underscore the idea that you can
|
||||
combing multiple database operations together in a single atomic
|
||||
unit of work. So for our example, we do the (slightly) wrong thing.
|
||||
</p>
|
||||
<p>
|
||||
Further, notice that we store our key into a
|
||||
<tt class="classname">DatabaseEntry</tt> using
|
||||
<tt class="classname">com.sleepycat.bind.tuple.StringBinding</tt> to
|
||||
perform the serialization. Also, when we instantiate the
|
||||
<tt class="classname">PayloadData</tt> object, we call
|
||||
<tt class="methodname">getName()</tt> which gives us the string
|
||||
representation of this thread's name, as well as
|
||||
<tt class="methodname">Random.nextDouble()</tt> which gives us a random
|
||||
double value. This latter value is used so as to avoid duplicate
|
||||
records in the database.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
// Write 10 records to the db
|
||||
// for each transaction
|
||||
for (int j = 0; j < 10; j++) {
|
||||
// Get the key
|
||||
DatabaseEntry key = new DatabaseEntry();
|
||||
StringBinding.stringToEntry(keys[j], key);
|
||||
|
||||
// Get the data
|
||||
PayloadData pd = new PayloadData(i+j, getName(),
|
||||
generator.nextDouble());
|
||||
DatabaseEntry data = new DatabaseEntry();
|
||||
dataBinding.objectToEntry(pd, data);
|
||||
|
||||
// Do the put
|
||||
myDb.put(txn, key, data);
|
||||
} </pre>
|
||||
<p>
|
||||
Having completed the inner database write loop, we could simply
|
||||
commit the transaction and continue on to the next block of 10
|
||||
writes. However, we want to first illustrate a few points about
|
||||
transactional processing so instead we call our
|
||||
<tt class="function">countRecords()</tt> method before calling the transaction
|
||||
commit. <tt class="function">countRecords()</tt> uses a cursor to read every
|
||||
record in the database and return a count of the number of records
|
||||
that it found.
|
||||
</p>
|
||||
<p>
|
||||
Because
|
||||
<tt class="function">countRecords()</tt>
|
||||
reads every record in the database, if used incorrectly the thread
|
||||
will self-deadlock. The writer thread has just written 500 records
|
||||
to the database, but because the transaction used for that write
|
||||
has not yet been committed, each of those 500 records are still
|
||||
locked by the thread's transaction. If we then simply run a
|
||||
non-transactional cursor over the database from within the same
|
||||
thread that has locked those 500 records, the cursor will
|
||||
block when it tries to read one of those transactional
|
||||
protected records. The thread immediately stops operation at that
|
||||
point while the cursor waits for the read lock it has
|
||||
requested. Because that read lock will never be released (the thread
|
||||
can never make any forward progress), this represents a
|
||||
self-deadlock for the thread.
|
||||
</p>
|
||||
<p>
|
||||
There are three ways to prevent this self-deadlock:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
We can move the call to
|
||||
<tt class="function">countRecords()</tt> to a point after the
|
||||
thread's transaction has committed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
We can allow <tt class="function">countRecords()</tt> to
|
||||
operate under the same transaction as all of the writes
|
||||
were performed.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
We can reduce our isolation guarantee for the application
|
||||
by allowing uncommitted reads.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>
|
||||
For this example, we choose to use option 3 (uncommitted reads) to avoid
|
||||
the deadlock. This means that we have to open our database such
|
||||
that it supports uncommitted reads, and we have to open our cursor handle
|
||||
so that it knows to perform uncommitted reads.
|
||||
</p>
|
||||
<p>
|
||||
Note that in <a href="inmem_txnexample_java.html">Base API In-Memory Transaction Example</a>,
|
||||
we simply perform the cursor operation using the same transaction
|
||||
as is used for the thread's writes.
|
||||
</p>
|
||||
<pre class="programlisting"> // commit
|
||||
System.out.println(getName() + " : committing txn : "
|
||||
+ i);
|
||||
|
||||
// Using uncommitted reads to avoid the deadlock, so null
|
||||
// is passed for the transaction here.
|
||||
System.out.println(getName() + " : Found " +
|
||||
countRecords(null) + " records in the database."); </pre>
|
||||
<p>
|
||||
Having performed this somewhat inelegant counting of the records in the
|
||||
database, we can now commit the transaction.
|
||||
</p>
|
||||
<pre class="programlisting"> try {
|
||||
txn.commit();
|
||||
txn = null;
|
||||
} catch (DatabaseException e) {
|
||||
System.err.println("Error on txn commit: " +
|
||||
e.toString());
|
||||
}
|
||||
retry = false; </pre>
|
||||
<p>
|
||||
If all goes well with the commit, we are done and we can move on to the
|
||||
next batch of 10 records to add to the database. However, in the event
|
||||
of an error, we must handle our exceptions correctly. The first of
|
||||
these is a deadlock exception. In the event of a deadlock, we want to
|
||||
abort and retry the transaction, provided that we have not already
|
||||
exceeded our retry limit for this transaction.
|
||||
</p>
|
||||
<pre class="programlisting"> } catch (DeadlockException de) {
|
||||
System.out.println("################# " + getName() +
|
||||
" : caught deadlock");
|
||||
// retry if necessary
|
||||
if (retry_count < MAX_RETRY) {
|
||||
System.err.println(getName() +
|
||||
" : Retrying operation.");
|
||||
retry = true;
|
||||
retry_count++;
|
||||
} else {
|
||||
System.err.println(getName() +
|
||||
" : out of retries. Giving up.");
|
||||
retry = false;
|
||||
} </pre>
|
||||
<p>
|
||||
In the event of a standard, non-specific database exception, we simply
|
||||
log the exception and then give up (the transaction is not retried).
|
||||
</p>
|
||||
<pre class="programlisting"> } catch (DatabaseException e) {
|
||||
// abort and don't retry
|
||||
retry = false;
|
||||
System.err.println(getName() +
|
||||
" : caught exception: " + e.toString());
|
||||
System.err.println(getName() +
|
||||
" : errno: " + e.getErrno());
|
||||
e.printStackTrace(); </pre>
|
||||
<p>
|
||||
And, finally, we always abort the transaction if the transaction handle
|
||||
is not null. Note that immediately after committing our transaction, we
|
||||
set the transaction handle to null to guard against aborting a
|
||||
transaction that has already been committed.
|
||||
</p>
|
||||
<pre class="programlisting"> } finally {
|
||||
if (txn != null) {
|
||||
try {
|
||||
txn.abort();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error aborting txn: " +
|
||||
e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
The final piece of our <tt class="classname">DBWriter</tt> class is the
|
||||
<tt class="methodname">countRecords()</tt> implementation. Notice how in
|
||||
this example we open the cursor such that it performs uncommitted
|
||||
reads:
|
||||
</p>
|
||||
<pre class="programlisting"> // A method that counts every record in the database.
|
||||
|
||||
// Note that this method exists only for illustrative purposes.
|
||||
// A more straight-forward way to count the number of records in
|
||||
// a database is to use the Database.getStats() method.
|
||||
private int countRecords(Transaction txn) throws DatabaseException {
|
||||
DatabaseEntry key = new DatabaseEntry();
|
||||
DatabaseEntry data = new DatabaseEntry();
|
||||
int count = 0;
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
// Get the cursor
|
||||
CursorConfig cc = new CursorConfig();
|
||||
cc.setReadUncomitted(true);
|
||||
cursor = myDb.openCursor(txn, cc);
|
||||
while (cursor.getNext(key, data, LockMode.DEFAULT) ==
|
||||
OperationStatus.SUCCESS) {
|
||||
|
||||
count++;
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
} </pre>
|
||||
</div>
|
||||
<p>
|
||||
This completes our transactional example. If you would like to
|
||||
experiment with this code, you can find the example in the following
|
||||
location in your DB distribution:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_java/src/db/txn</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="wrapup.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="wrapup.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txnexample_dpl.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 6. Summary and Examples </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> DPL Transaction Example</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
165
docs/gsg_txn/JAVA/txnindices.html
Normal file
165
docs/gsg_txn/JAVA/txnindices.html
Normal file
@@ -0,0 +1,165 @@
|
||||
<?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>Secondary Indices with Transaction 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="usingtxns.html" title="Chapter 3. Transaction Basics" />
|
||||
<link rel="previous" href="txncursor.html" title="Transactional Cursors" />
|
||||
<link rel="next" href="maxtxns.html" title="Configuring the Transaction Subsystem" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Secondary Indices with Transaction Applications</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="txncursor.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 3. Transaction Basics</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="maxtxns.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="txnindices"></a>Secondary Indices with Transaction Applications</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<span>
|
||||
If you are using the base API, then you
|
||||
</span>
|
||||
|
||||
can use transactions with your secondary indices so long as you
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
open the secondary index so that it is transactional.
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
All other aspects of using secondary indices with transactions are
|
||||
identical to using secondary indices without transactions. In
|
||||
addition, transaction-protecting
|
||||
|
||||
<span>
|
||||
secondary cursors is performed just as you protect normal
|
||||
cursors — you simply have to make sure the cursor is
|
||||
opened using a transaction handle, and that the cursor is
|
||||
closed before the handle is either either committed or
|
||||
aborted.
|
||||
</span>
|
||||
See <a href="txncursor.html">Transactional Cursors</a> for details.
|
||||
</p>
|
||||
<p>
|
||||
Note that when you use transactions to protect your database writes, your secondary indices are protected from
|
||||
corruption because updates to the primary and the secondaries are performed in a single atomic transaction.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
If you are using the DPL, then be aware that
|
||||
you never have to provide a transactional
|
||||
handle when opening an index, be it a primary
|
||||
or a secondary. However, transactions are
|
||||
enabled for your store, then all of the indexes
|
||||
that you open will be enabled for transactional
|
||||
usage. More, any write operation performed
|
||||
using that index will be done using a
|
||||
transaction, regardless of whether you
|
||||
explictly provide a transactional handle to the
|
||||
write operation.
|
||||
</p>
|
||||
<p>
|
||||
If you do not explictly provide a transaction
|
||||
handle to DPL write operations performed on a
|
||||
transactional store, then auto commit is
|
||||
silently used for that operation.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting">package db.GettingStarted;
|
||||
|
||||
import com.sleepycat.bind.tuple.TupleBinding;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseType;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.SecondaryDatabase;
|
||||
import com.sleepycat.db.SecondaryConfig;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
// Environment and primary database opens omitted.
|
||||
|
||||
SecondaryConfig mySecConfig = new SecondaryConfig();
|
||||
mySecConfig.setAllowCreate(true);
|
||||
mySecConfig.setType(DatabaseType.BTREE);
|
||||
mySecConfig.setTransactional(true);
|
||||
|
||||
SecondaryDatabase mySecDb = null;
|
||||
try {
|
||||
// A fake tuple binding that is not actually implemented anywhere.
|
||||
// The tuple binding is dependent on the data in use.
|
||||
// See the Getting Started Guide for details
|
||||
TupleBinding myTupleBinding = new MyTupleBinding();
|
||||
|
||||
// Open the secondary. FullNameKeyCreator is not actually implemented
|
||||
// anywhere. See the Getting Started Guide for details.
|
||||
FullNameKeyCreator keyCreator = new FullNameKeyCreator(myTupleBinding);
|
||||
|
||||
// Set the key creator on the secondary config object.
|
||||
mySecConfig.setKeyCreator(keyCreator);
|
||||
|
||||
// Perform the actual open. Because this database is configured to be
|
||||
// transactional, the open is automatically wrapped in a transaction.
|
||||
// - myEnv is the environment handle.
|
||||
// - myDb is the primary database handle.
|
||||
String secDbName = "mySecondaryDatabase";
|
||||
mySecDb = myEnv.openSecondary(null, secDbName, null, myDb, mySecConfig);
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here ...
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here ...
|
||||
}</pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="txncursor.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="usingtxns.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="maxtxns.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Transactional Cursors </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Configuring the Transaction Subsystem</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
91
docs/gsg_txn/JAVA/txnnowait.html
Normal file
91
docs/gsg_txn/JAVA/txnnowait.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<?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>No Wait on Blocks</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="readmodifywrite.html" title="Read/Modify/Write" />
|
||||
<link rel="next" href="reversesplit.html" title="Reverse BTree Splits" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">No Wait on Blocks</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="readmodifywrite.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Concurrency</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="reversesplit.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="txnnowait"></a>No Wait on Blocks</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Normally when a DB transaction is blocked on a lock request, it
|
||||
must wait until the requested lock becomes available before its
|
||||
thread-of-control can proceed. However, it is possible to configure a
|
||||
transaction handle such that it will report a deadlock rather
|
||||
than wait for the block to clear.
|
||||
</p>
|
||||
<p>
|
||||
You do this on a transaction by transaction basis by specifying
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt>
|
||||
to the
|
||||
<tt class="methodname">TransactionConfig.setNoWait()</tt>
|
||||
method.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre class="programlisting"> Transaction txn = null;
|
||||
try {
|
||||
TransactionConfig tc = new TransactionConfig();
|
||||
tc.setNoWait(true);
|
||||
txn = myEnv.beginTransaction(null, tc);
|
||||
|
||||
...
|
||||
} catch (DatabaseException de) {
|
||||
// Deadlock detection and exception handling omitted
|
||||
// for brevity
|
||||
... </pre>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="readmodifywrite.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="reversesplit.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Read/Modify/Write </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Reverse BTree Splits</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
620
docs/gsg_txn/JAVA/usingtxns.html
Normal file
620
docs/gsg_txn/JAVA/usingtxns.html
Normal file
@@ -0,0 +1,620 @@
|
||||
<?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>Chapter 3. Transaction Basics</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="envopen.html" title="Opening a Transactional Environment and Store or Database " />
|
||||
<link rel="next" href="abortresults.html" title="Aborting a Transaction" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 3. Transaction Basics</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="envopen.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="abortresults.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="usingtxns"></a>Chapter 3. Transaction Basics</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="usingtxns.html#commitresults">Committing a Transaction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="abortresults.html">Aborting a Transaction</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="autocommit.html">Auto Commit</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="nestedtxn.html">Nested Transactions</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txncursor.html">Transactional Cursors</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txncursor.html#dplcursors">Using Transactional DPL Cursors</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnindices.html">Secondary Indices with Transaction Applications</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="maxtxns.html">Configuring the Transaction Subsystem</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
Once you have enabled transactions for your environment and your databases,
|
||||
you can use them to protect your database operations. You do this by
|
||||
acquiring a transaction handle and then using that handle for any
|
||||
database operation that you want to participate in that transaction.
|
||||
</p>
|
||||
<p>
|
||||
You obtain a transaction handle using the
|
||||
|
||||
|
||||
<span><tt class="methodname">Environment.beginTransaction()</tt> method.</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Once you have completed all of the operations that you want to include
|
||||
in the transaction, you must commit the transaction using the
|
||||
|
||||
|
||||
<span><tt class="methodname">Transaction.commit()</tt> method.</span>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
If, for any reason, you want to abandon the transaction, you abort
|
||||
it using
|
||||
|
||||
|
||||
<span><tt class="methodname">Transaction.abort()</tt>.</span>
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Any transaction handle that has been committed or aborted can no longer
|
||||
be used by your application.
|
||||
</p>
|
||||
<p>
|
||||
Finally, you must make sure that all transaction handles are either
|
||||
committed or aborted before closing your databases and environment.
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
If you only want to transaction protect a single database write operation, you can use auto commit to
|
||||
perform the transaction administration. When you use auto commit, you do not need an explicit transaction
|
||||
handle. See <a href="autocommit.html">Auto Commit</a> for more information.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
For example, the following example opens a transactional-enabled environment and
|
||||
store, obtains a transaction handle, and then performs a write
|
||||
operation under its protection. In the event of any failure in the
|
||||
write operation, the transaction is aborted and the store is left in a
|
||||
state as if no operations had ever been attempted in the first place.
|
||||
|
||||
</p>
|
||||
<pre class="programlisting">package persist.txn;
|
||||
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.StoreConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Environment myEnv = null;
|
||||
EntityStore store = null;
|
||||
|
||||
// Our convenience data accessor class, used for easy access to
|
||||
// EntityClass indexes.
|
||||
DataAccessor da;
|
||||
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
StoreConfig storeConfig = new StoreConfig();
|
||||
storeConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
EntityStore store = new EntityStore(myEnv,
|
||||
"EntityStore", storeConfig);
|
||||
|
||||
da = new DataAccessor(store);
|
||||
|
||||
// Assume that Inventory is an entity class.
|
||||
Inventory theInventory = new Inventory();
|
||||
theInventory.setItemName("Waffles");
|
||||
theInventory.setItemSku("waf23rbni");
|
||||
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
|
||||
try {
|
||||
// Put the object to the store using the transaction handle.
|
||||
da.inventoryBySku.put(txn, theInventory);
|
||||
|
||||
// Commit the transaction. The data is now safely written to the
|
||||
// store.
|
||||
txn.commit();
|
||||
// If there is a problem, abort the transaction
|
||||
} catch (Exception e) {
|
||||
if (txn != null) {
|
||||
txn.abort();
|
||||
txn = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
}</pre>
|
||||
<p>
|
||||
The same thing can be done with the base API. In this case, the
|
||||
database in use is left unchanged if the write operation fails:
|
||||
</p>
|
||||
<pre class="programlisting">package db.txn;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseConfig;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Environment;
|
||||
import com.sleepycat.db.EnvironmentConfig;
|
||||
import com.sleepycat.db.Transaction;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
...
|
||||
|
||||
Database myDatabase = null;
|
||||
Environment myEnv = null;
|
||||
try {
|
||||
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
|
||||
myEnvConfig.setInitializeCache(true);
|
||||
myEnvConfig.setInitializeLocking(true);
|
||||
myEnvConfig.setInitializeLogging(true);
|
||||
myEnvConfig.setTransactional(true);
|
||||
|
||||
myEnv = new Environment(new File("/my/env/home"),
|
||||
myEnvConfig);
|
||||
|
||||
// Open the database.
|
||||
DatabaseConfig dbConfig = new DatabaseConfig();
|
||||
dbConfig.setTransactional(true);
|
||||
dbConfig.setType(DatabaseType.BTREE);
|
||||
myDatabase = myEnv.openDatabase(null, // txn handle
|
||||
"sampleDatabase", // db file name
|
||||
null, // db name
|
||||
dbConfig);
|
||||
String keyString = "thekey";
|
||||
String dataString = "thedata";
|
||||
DatabaseEntry key =
|
||||
new DatabaseEntry(keyString.getBytes("UTF-8"));
|
||||
DatabaseEntry data =
|
||||
new DatabaseEntry(dataString.getBytes("UTF-8"));
|
||||
|
||||
Transaction txn = myEnv.beginTransaction(null, null);
|
||||
|
||||
try {
|
||||
myDatabase.put(txn, key, data);
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
if (txn != null) {
|
||||
txn.abort();
|
||||
txn = null;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (DatabaseException de) {
|
||||
// Exception handling goes here
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Exception handling goes here
|
||||
} </pre>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="commitresults"></a>Committing a Transaction</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
In order to fully understand what is happening when you commit
|
||||
a transaction, you must first understand a little about what
|
||||
DB is doing with
|
||||
|
||||
<span>
|
||||
the logging subsystem.
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
Logging causes all database <span>or
|
||||
store</span> write operations to be identified in
|
||||
|
||||
<span>logs, and by default these
|
||||
logs are backed by files on disk. These logs are used to restore your databases
|
||||
<span>or store</span>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
in the event of a system or application failure, so by performing
|
||||
logging, DB ensures the integrity of your data.
|
||||
</p>
|
||||
<p>
|
||||
Moreover, DB performs <span class="emphasis"><em>write-ahead</em></span>
|
||||
logging. This means that information is written to the logs
|
||||
<span class="emphasis"><em>before</em></span> the actual database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
is changed.
|
||||
This means that all write activity performed under the
|
||||
protection of the transaction is noted in the log before
|
||||
the transaction is committed. Be aware, however, that database
|
||||
maintains logs in-memory. If you are backing your logs on
|
||||
disk, the log information will eventually be written to the log
|
||||
files, but while the transaction is on-going the log data may be
|
||||
held only in memory.
|
||||
</p>
|
||||
<p>
|
||||
When you commit a transaction, the following occurs:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
A commit record is written to the log. This
|
||||
indicates that the modifications made by the
|
||||
transaction are now permanent. By default, this write is performed synchronously to disk so the
|
||||
commit record arrives in the log files before any other actions are taken.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Any log information held in memory is (by default)
|
||||
synchronously written to disk. Note that this requirement can be
|
||||
relaxed, depending on the type of commit you perform.
|
||||
See <a href="usingtxns.html#nodurabletxn">Non-Durable Transactions</a> for
|
||||
more information.
|
||||
<span>Also, if you are
|
||||
maintaining your logs entirely in-memory, then this
|
||||
step will of course not be taken. To configure your
|
||||
logging system for in-memory usage, see
|
||||
<a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
All locks held by the transaction are released. This means
|
||||
that read operations performed by other transactions or
|
||||
threads of control can now see the modifications without
|
||||
resorting to uncommitted reads (see <a href="isolation.html#dirtyreads">Reading Uncommitted Data</a> for more information).
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
To commit a transaction, you simply call
|
||||
|
||||
|
||||
<span><tt class="methodname">Transaction.commit()</tt>.</span>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Notice that committing a transaction does not necessarily cause data
|
||||
modified in your memory cache to be written to the files
|
||||
backing your databases on disk. Dirtied database pages are written
|
||||
for a number of reasons, but a transactional
|
||||
commit is not one of them. The following are the things that can cause a dirtied
|
||||
database page to be written to the backing database file:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Checkpoints.
|
||||
</p>
|
||||
<p>
|
||||
Checkpoints cause all dirtied pages currently existing
|
||||
in the cache to be written to disk, and a checkpoint
|
||||
record is then written to the logs. You can run checkpoints
|
||||
explicitly. For more information on checkpoints,
|
||||
see <a href="filemanagement.html#checkpoints">Checkpoints</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Cache is full.
|
||||
</p>
|
||||
<p>
|
||||
If the in-memory cache fills up, then dirtied pages
|
||||
might be written to disk in order to free up space for other
|
||||
pages that your application needs to use. Note that if
|
||||
dirtied pages are written to the database files, then
|
||||
any log records that describe how those pages were
|
||||
dirtied are written to disk before the database
|
||||
pages are written.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
Be aware that because your transaction commit caused database
|
||||
<span>
|
||||
or store
|
||||
</span>
|
||||
modifications recorded in your logs to be forced to disk, your modifications
|
||||
are by default "persistent" in that they can be recovered in the event of
|
||||
an application or system failure. However, recovery time is
|
||||
gated by how much data has been modified since the last
|
||||
checkpoint, so for applications that perform a lot of writes,
|
||||
you may want to run a checkpoint with some frequency.
|
||||
</p>
|
||||
<p>
|
||||
Note that once you have committed a transaction, the transaction
|
||||
handle that you used for the transaction is no longer valid. To
|
||||
perform database activities under the control of a new
|
||||
transaction, you must obtain a fresh transaction handle.
|
||||
</p>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="nodurabletxn"></a>Non-Durable Transactions</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
As previously noted, by default transaction commits are
|
||||
durable because they cause the modifications performed
|
||||
under the transaction to be synchronously recorded in
|
||||
your on-disk log files. However, it is possible to use
|
||||
non-durable transactions.
|
||||
</p>
|
||||
<p>
|
||||
You may want non-durable transactions for performance
|
||||
reasons. For example, you might be using transactions
|
||||
simply for the isolation guarantee.
|
||||
|
||||
<span>
|
||||
In this case, you might
|
||||
not want a durability guarantee and so you may want to
|
||||
prevent the disk I/O that normally accompanies a
|
||||
transaction commit.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
There are several ways to remove the durability guarantee
|
||||
for your transactions:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Specify
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setTxnNoSync()</tt>
|
||||
|
||||
method.
|
||||
</span>
|
||||
This causes DB to not synchronously force any
|
||||
<span>
|
||||
log
|
||||
</span>
|
||||
data to disk upon transaction commit.
|
||||
|
||||
<span>
|
||||
That is, the modifications are held entirely
|
||||
in the in-memory cache and the logging
|
||||
information is not forced to the filesystem for
|
||||
long-term storage.
|
||||
</span>
|
||||
|
||||
Note, however, that the
|
||||
<span>
|
||||
logging
|
||||
</span>
|
||||
data will eventually make it to the filesystem (assuming no
|
||||
application or OS crashes) as a part of DB's
|
||||
management of its logging buffers and/or cache.
|
||||
</p>
|
||||
<p>
|
||||
This form of a commit provides a weak durability
|
||||
guarantee because data loss can occur due to
|
||||
an application<span>, JVM,</span>
|
||||
or OS crash.
|
||||
</p>
|
||||
<p>
|
||||
This behavior is specified on a per-environment
|
||||
handle basis. In order for your application to exhibit consistent
|
||||
behavior, you need to specify this
|
||||
|
||||
<span>method</span>
|
||||
for all of the environment handles used in your application.
|
||||
</p>
|
||||
<p>
|
||||
You can achieve this behavior on a transaction by transaction basis by
|
||||
|
||||
|
||||
<span>
|
||||
using <tt class="methodname">Transaction.commitNoSync()</tt>
|
||||
|
||||
to commit your transaction, or by specifying <tt class="literal">true</tt> to the
|
||||
<tt class="methodname">TransactionConfig.setNoSync()</tt> method when starting the
|
||||
transaction.
|
||||
</span>
|
||||
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Specify
|
||||
|
||||
|
||||
<span>
|
||||
<tt class="literal">true</tt> to the
|
||||
<tt class="methodname">EnvironmentConfig.setTxnWriteNoSync()</tt>
|
||||
method.
|
||||
</span>
|
||||
|
||||
This causes
|
||||
<span>
|
||||
logging
|
||||
</span>
|
||||
data to be synchronously
|
||||
written to the OS's file system buffers upon
|
||||
transaction commit. The data will eventually be
|
||||
written to disk, but this occurs when the
|
||||
operating system chooses to schedule the
|
||||
activity; the transaction commit can complete
|
||||
successfully before this disk I/O is performed
|
||||
by the OS.
|
||||
</p>
|
||||
<p>
|
||||
This form of commit protects you against application
|
||||
<span>and JVM</span> crashes, but not against OS
|
||||
crashes. This method offers less room for the possibility of data loss than does
|
||||
|
||||
<span><tt class="methodname">EnvironmentConfig.setTxnNoSync()</tt>.</span>
|
||||
</p>
|
||||
<p>
|
||||
This behavior is specified on a per-environment
|
||||
handle basis. In order for your application to exhibit consistent
|
||||
behavior, you need to specify this
|
||||
|
||||
<span>method</span>
|
||||
for all of the environment handles used in your application.
|
||||
</p>
|
||||
<p>
|
||||
You can achieve this behavior on a transaction by transaction basis by
|
||||
<span>
|
||||
using <tt class="methodname">Transaction.commitWriteNoSync()</tt>
|
||||
to commit your transaction, or by specifying <tt class="literal">true</tt> to
|
||||
<tt class="methodname">TransactionConfig.setWriteNoSync()</tt> method when starting the
|
||||
transaction.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Maintain your logs entirely in-memory. In this
|
||||
case, your logs are never written to disk. The
|
||||
result is that you lose all durability guarantees.
|
||||
See
|
||||
<a href="logconfig.html#inmemorylogging">Configuring In-Memory Logging</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="envopen.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="abortresults.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Opening a Transactional Environment and
|
||||
|
||||
Store or Database
|
||||
|
||||
</td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Aborting a Transaction</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
327
docs/gsg_txn/JAVA/wrapup.html
Normal file
327
docs/gsg_txn/JAVA/wrapup.html
Normal file
@@ -0,0 +1,327 @@
|
||||
<?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>Chapter 6. Summary and Examples</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="index.html" title="Getting Started with Berkeley DB Transaction Processing" />
|
||||
<link rel="previous" href="logconfig.html" title="Configuring the Logging Subsystem" />
|
||||
<link rel="next" href="txnexample_java.html" title="Base API Transaction Example" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 6. Summary and Examples</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="logconfig.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="txnexample_java.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="wrapup"></a>Chapter 6. Summary and Examples</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="wrapup.html#anatomy">Anatomy of a Transactional Application</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnexample_java.html">Base API Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#txnguideexample">TxnGuide.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#payloaddata">PayloadData.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_java.html#dbwriter">DBWriter.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="txnexample_dpl.html">DPL Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#txnguideexample_dpl">TxnGuide.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#payloaddataentity">PayloadDataEntity.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect2">
|
||||
<a href="txnexample_dpl.html#storewriter">StoreWriter.java</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="inmem_txnexample_java.html">Base API In-Memory Transaction Example</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
Throughout this manual we have presented the concepts and
|
||||
mechanisms that you need to provide transactional protection for
|
||||
your application. In this chapter, we summarize these
|
||||
mechanisms, and we provide a complete example of a multi-threaded
|
||||
transactional DB application.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="anatomy"></a>Anatomy of a Transactional Application</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Transactional applications are characterized by performing the
|
||||
following activities:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="1">
|
||||
<li>
|
||||
<p>
|
||||
Create your environment handle.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Open your environment, specifying that the following
|
||||
subsystems be used:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Transactional Subsystem (this also initializes the
|
||||
logging subsystem).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Memory pool (the in-memory cache).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Logging subsystem.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Locking subsystem (if your application is multi-process or multi-threaded).
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
It is also highly recommended that you run normal recovery
|
||||
upon first environment open. Normal recovery examines only those logs required
|
||||
to ensure your database files are consistent relative to the information found in your
|
||||
log files.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Optionally spawn off any utility threads that you might need. Utility
|
||||
threads can be used to run checkpoints periodically, or to
|
||||
periodically run a deadlock detector if you do not want to
|
||||
use DB's built-in deadlock detector.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
If you are using the base API, open whatever database handles
|
||||
that you need. Otherwise, open your store such that it is
|
||||
configured for transactions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Spawn off worker threads. How many of these you need and
|
||||
how they split their DB workload is entirely up to your
|
||||
application's requirements. However, any worker threads
|
||||
that perform write operations will do the following:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="a">
|
||||
<li>
|
||||
<p>
|
||||
Begin a transaction.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Perform one or more read and write
|
||||
operations.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Commit the transaction if all goes well.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Abort and retry the operation if a deadlock is
|
||||
detected.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Abort the transaction for most other errors.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
On application shutdown:
|
||||
</p>
|
||||
<div class="orderedlist">
|
||||
<ol type="a">
|
||||
<li>
|
||||
<p>
|
||||
Make sure there are no opened cursors.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Make sure there are no active transactions. Either
|
||||
abort or commit all transactions before shutting
|
||||
down.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Close your databases or store.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Close your environment.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Robust DB applications should monitor their worker threads to
|
||||
make sure they have not died unexpectedly. If a thread does
|
||||
terminate abnormally, you must shutdown all your worker threads
|
||||
and then run normal recovery (you will have to reopen your
|
||||
environment to do this). This is the only way to clear any
|
||||
resources (such as a lock or a mutex) that the abnormally
|
||||
exiting worker thread might have been holding at the time that
|
||||
it died.
|
||||
</p>
|
||||
<p>
|
||||
Failure to perform this recovery can cause your
|
||||
still-functioning worker threads to eventually block forever
|
||||
while waiting for a lock that will never be released.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
In addition to these activities, which are all entirely handled by
|
||||
code within your application, there are some administrative
|
||||
activities that you should perform:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
Periodically checkpoint your application. Checkpoints will
|
||||
reduce the time to run recovery in the event that one is
|
||||
required. See <a href="filemanagement.html#checkpoints">Checkpoints</a>
|
||||
for details.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Periodically back up your database and log files. This is
|
||||
required in order to fully obtain the durability guarantee
|
||||
made by DB's transaction ACID support. See
|
||||
<a href="backuprestore.html">Backup Procedures</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
You may want to maintain a hot failover if 24x7 processing
|
||||
with rapid restart in the face of a disk hit is important
|
||||
to you. See <a href="hotfailover.html">Using Hot Failovers</a>
|
||||
for more information.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="logconfig.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="txnexample_java.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Configuring the Logging Subsystem </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Base API Transaction Example</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/gsg_txn/JAVA/writeblock.jpg
Normal file
BIN
docs/gsg_txn/JAVA/writeblock.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
Reference in New Issue
Block a user