mirror of
https://github.com/yasuhirokimura/db18
synced 2026-06-08 18:29:23 +00:00
234 lines
12 KiB
HTML
234 lines
12 KiB
HTML
<?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>Degrees of isolation</title>
|
||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
|
||
<link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
|
||
<link rel="up" href="transapp.html" title="Chapter 11. Berkeley DB Transactional Data Store Applications" />
|
||
<link rel="prev" href="transapp_inc.html" title="Isolation" />
|
||
<link rel="next" href="transapp_cursor.html" title="Transactional cursors" />
|
||
</head>
|
||
<body>
|
||
<div xmlns="" class="navheader">
|
||
<div class="libver">
|
||
<p>Library Version 18.1.40</p>
|
||
</div>
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Degrees of isolation</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="transapp_inc.html">Prev</a> </td>
|
||
<th width="60%" align="center">Chapter 11. Berkeley DB Transactional Data Store Applications </th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="transapp_cursor.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="transapp_read"></a>Degrees of isolation</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="toc">
|
||
<dl>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="transapp_read.html#snapshot_isolation">Snapshot Isolation</a>
|
||
</span>
|
||
</dt>
|
||
</dl>
|
||
</div>
|
||
<p>
|
||
Transactions can be isolated from each other to different
|
||
degrees. <span class="emphasis"><em>Serializable</em></span> provides the most
|
||
isolation, and means that, for the life of the transaction,
|
||
every time a thread of control reads a data item, it will be
|
||
unchanged from its previous value (assuming, of course, the
|
||
thread of control does not itself modify the item). By
|
||
default, Berkeley DB enforces serializability whenever
|
||
database reads are wrapped in transactions. This is also known
|
||
as <span class="emphasis"><em>degree 3 isolation</em></span>.
|
||
</p>
|
||
<p>
|
||
Most applications do not need to enclose all reads in
|
||
transactions, and when possible, transactionally protected
|
||
reads at serializable isolation should be avoided as they can
|
||
cause performance problems. For example, a serializable cursor
|
||
sequentially reading each key/data pair in a database, will
|
||
acquire a read lock on most of the pages in the database and
|
||
so will gradually block all write operations on the databases
|
||
until the transaction commits or aborts. Note, however, that
|
||
if there are update transactions present in the application,
|
||
the read operations must still use locking, and must be
|
||
prepared to repeat any operation (possibly closing and
|
||
reopening a cursor) that fails with a return value of <a class="link" href="program_errorret.html#program_errorret.DB_LOCK_DEADLOCK">DB_LOCK_DEADLOCK</a>.
|
||
Applications that need repeatable reads are ones that require
|
||
the ability to repeatedly access a data item knowing that it will
|
||
not have changed (for example, an operation modifying a data item based
|
||
on its existing value).
|
||
</p>
|
||
<p>
|
||
<span class="emphasis"><em>Snapshot isolation</em></span> is a second mechanism
|
||
for providing serializability, favoring reader over updaters.
|
||
With multiversion concurrency control (MVCC), rather than
|
||
requiring readers to get a read lock when looking
|
||
at a page, it is the updaters which do most of the work
|
||
to support <span class="emphasis"><em>degree 3 isolation</em></span>. This
|
||
makes update operations more expensive, because
|
||
they have to allocate space for new
|
||
versions of pages in cache and make copies, but avoiding read
|
||
locks can significantly increase throughput for many
|
||
applications. Snapshot isolation is discussed in detail
|
||
below.
|
||
</p>
|
||
<p>
|
||
A transaction may only require <span class="emphasis"><em>cursor
|
||
stability</em></span>, that is only be guaranteed that
|
||
cursors see committed data that does not change so long as it
|
||
is addressed by the cursor, but may change before the reading
|
||
transaction completes. This is also called <span class="emphasis"><em>degree 2
|
||
isolation</em></span>. Berkeley DB provides this level of
|
||
isolation when a transaction is started with the
|
||
<a href="../api_reference/C/dbcget.html#dbcget_DB_READ_COMMITTED" class="olink">DB_READ_COMMITTED</a> flag. This flag may also be specified when
|
||
opening a cursor within a fully isolated transaction.
|
||
</p>
|
||
<p>
|
||
Berkeley DB optionally supports reading uncommitted data;
|
||
that is, read operations may request data which has been
|
||
modified but not yet committed by another transaction. This is
|
||
also called <span class="emphasis"><em>degree 1 isolation</em></span>. This is
|
||
done by first specifying the <a href="../api_reference/C/dbopen.html#dbopen_DB_READ_UNCOMMITTED" class="olink">DB_READ_UNCOMMITTED</a> flag when
|
||
opening the underlying database, and then specifying the
|
||
<a href="../api_reference/C/dbopen.html#dbopen_DB_READ_UNCOMMITTED" class="olink">DB_READ_UNCOMMITTED</a> flag when beginning a transaction,
|
||
opening a cursor, or performing a read operation. The
|
||
advantage of using <a href="../api_reference/C/dbopen.html#dbopen_DB_READ_UNCOMMITTED" class="olink">DB_READ_UNCOMMITTED</a> is that read
|
||
operations will not block when another transaction holds a
|
||
write lock on the requested data; the disadvantage is that
|
||
read operations may return data that will disappear should the
|
||
transaction holding the write lock abort.
|
||
</p>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="snapshot_isolation"></a>Snapshot Isolation</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
<span class="emphasis"><em>Snapshot isolation</em></span> occurs when MVCC-enabled databases
|
||
are accessed by <a href="../api_reference/C/txnbegin.html#txnbegin_DB_TXN_SNAPSHOT" class="olink">DB_TXN_SNAPSHOT</a> transactions. An application first includes
|
||
<a href="../api_reference/C/dbopen.html#dbopen_DB_MULTIVERSION" class="olink">DB_MULTIVERSION</a> when opening databases for which snapshot
|
||
isolation is desired. The application completes the configuration
|
||
of snapshot isolation by including <a href="../api_reference/C/txnbegin.html#txnbegin_DB_TXN_SNAPSHOT" class="olink">DB_TXN_SNAPSHOT</a> when beginning
|
||
a transaction or cursor.
|
||
</p>
|
||
<p>
|
||
Usually snapshot isolation is configured on each
|
||
database and transaction where it is desired. Occasionally it is
|
||
useful to set snapshot isolation for the entire environment handle:
|
||
</p>
|
||
<pre class="programlisting">dbenv->set_flags(dbenv, DB_MULTIVERSION, 1);
|
||
dbenv->set_flags(dbenv, DB_TXN_SNAPSHOT, 1);</pre>
|
||
<p>
|
||
This can be valuable for replication clients which offload read
|
||
requests from the master site.
|
||
</p>
|
||
<p>
|
||
When configuring an environment for snapshot isolation,
|
||
it is important to realize that having multiple versions
|
||
of pages in cache means that the working set will take up
|
||
more of the cache. As a result, snapshot isolation is best
|
||
suited for use with larger cache sizes.
|
||
</p>
|
||
<p>
|
||
If the cache becomes full of page copies before the old
|
||
copies can be discarded, additional I/O will occur as
|
||
pages are written to temporary "freezer" files. This can
|
||
substantially reduce throughput, and should be avoided if
|
||
possible by configuring a large cache and keeping snapshot
|
||
isolation transactions short. The amount of cache required
|
||
to avoid freezing buffers can be estimated by taking a
|
||
checkpoint followed by a call to <a href="../api_reference/C/logarchive.html" class="olink">DB_ENV->log_archive()</a>. The amount
|
||
of cache required is approximately double the size of logs
|
||
that remains.
|
||
</p>
|
||
<p>
|
||
The environment should also be configured for sufficient
|
||
transactions using <a href="../api_reference/C/envset_tx_max.html" class="olink">DB_ENV->set_tx_max()</a>. The maximum number of
|
||
transactions needs to include all transactions executed
|
||
concurrently by the application plus all cursors
|
||
configured for snapshot isolation. Further, the
|
||
transactions are retained until the last page they created
|
||
is evicted from cache, so in the extreme case, an
|
||
additional transaction may be needed for each page in the
|
||
cache. Note that cache sizes under 500MB are increased by
|
||
25%, so the calculation of number of pages needs to take
|
||
this into account.
|
||
</p>
|
||
<p>
|
||
So when <span class="emphasis"><em>should</em></span> applications use
|
||
snapshot isolation?
|
||
</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
There is a large cache relative to size of
|
||
updates performed by concurrent transactions;
|
||
and
|
||
</li>
|
||
<li>
|
||
Read/write contention is limiting the throughput
|
||
of the application; or
|
||
</li>
|
||
<li>
|
||
The application is all or mostly read-only.
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>
|
||
The simplest way to take advantage of snapshot isolation
|
||
is for queries: keep update transactions using full
|
||
read/write locking and set <a href="../api_reference/C/txnbegin.html#txnbegin_DB_TXN_SNAPSHOT" class="olink">DB_TXN_SNAPSHOT</a> on read-only
|
||
transactions or cursors. This should minimize blocking of
|
||
snapshot isolation transactions and will avoid introducing
|
||
new <a class="link" href="program_errorret.html#program_errorret.DB_LOCK_DEADLOCK">DB_LOCK_DEADLOCK</a> errors.
|
||
</p>
|
||
<p>
|
||
If the application has update transactions which read
|
||
many items and only update a small set (for example,
|
||
scanning until a desired record is found, then modifying
|
||
it), throughput may be improved by running some updates at
|
||
snapshot isolation as well.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="transapp_inc.html">Prev</a> </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="u" href="transapp.html">Up</a>
|
||
</td>
|
||
<td width="40%" align="right"> <a accesskey="n" href="transapp_cursor.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"> Transactional cursors</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|