458 lines
28 KiB
HTML
458 lines
28 KiB
HTML
<!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>Transactions and Concurrency — Doctrine MongoDB ODM 1.1.5 documentation</title>
|
|
<link rel="stylesheet" href="../_static/bootstrap/css/bootstrap.min.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/layout.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/configurationblock.css" type="text/css" />
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT: '../',
|
|
VERSION: '1.1.5',
|
|
COLLAPSE_MODINDEX: false,
|
|
FILE_SUFFIX: '.html',
|
|
HAS_SOURCE: true
|
|
};
|
|
</script>
|
|
|
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|
<script type="text/javascript" src="../_static/configurationblock.js"></script>
|
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|
<script type="text/javascript" src="../_static/configurationblock.js"></script>
|
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
|
<script type="text/javascript" src="../_static/configurationblock.js"></script>
|
|
<script src="../_static/bootstrap/js/bootstrap.min.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
<!--
|
|
$(document).ready(function() {
|
|
$("#versions").change(function() {
|
|
var docsUrl = $(this).val();
|
|
window.location.href = docsUrl;
|
|
});
|
|
});
|
|
-->
|
|
</script>
|
|
<link rel="shortcut icon" href="../_static/doctrine.ico"/>
|
|
<link rel="search" title="Search" href="../search.html" />
|
|
<link rel="top" title="Doctrine MongoDB ODM 1.1.5 documentation" href="../index.html" />
|
|
</head>
|
|
<body>
|
|
<div id="wrapper">
|
|
<div id="header">
|
|
<h1 id="h1title"></h1>
|
|
<div id="logo">
|
|
<a href="http://www.doctrine-project.org/">Doctrine - PHP Database Libraries</a>
|
|
</div>
|
|
</div>
|
|
<div id="nav" class="cls">
|
|
<div class="tl cls">
|
|
<ul>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/">Home</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/about.html">About</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/projects.html">Projects</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/contribute.html">Contribute</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/community.html">Community</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/archive.html">Blog</a></li>
|
|
<li><a target="_top" href="http://www.doctrine-project.org/jira">Development</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="content" class="cls">
|
|
<div class="related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li><a href="/">Doctrine Homepage</a> »</li>
|
|
<li><a href="../index.html">Doctrine MongoDB ODM 1.1.5 documentation</a> »</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
|
|
<div class="body" >
|
|
|
|
<div class="section" id="transactions-and-concurrency">
|
|
<h1>Transactions and Concurrency<a class="headerlink" href="#transactions-and-concurrency" title="Permalink to this headline">¶</a></h1>
|
|
<div class="section" id="transactions">
|
|
<h2>Transactions<a class="headerlink" href="#transactions" title="Permalink to this headline">¶</a></h2>
|
|
<p>As per the <a class="reference external" href="https://docs.mongodb.com/manual/core/write-operations-atomicity/#atomicity-and-transactions">documentation</a>, MongoDB
|
|
write operations are "atomic on the level of a single document".</p>
|
|
<p>Even when updating multiple documents within a single write operation,
|
|
though the modification of each document is atomic,
|
|
the operation as a whole is not and other operations may interleave.</p>
|
|
<p>As stated in the <a class="reference external" href="https://docs.mongodb.com/manual/faq/fundamentals/#does-mongodb-support-transactions">FAQ</a>,
|
|
"MongoDB does not support multi-document transactions" and neither does Doctrine MongoDB ODM.</p>
|
|
<div class="section" id="limitation">
|
|
<h3>Limitation<a class="headerlink" href="#limitation" title="Permalink to this headline">¶</a></h3>
|
|
<p>At the moment, Doctrine MongoDB ODM does not provide any native strategy to emulate multi-document transactions.</p>
|
|
</div>
|
|
<div class="section" id="workaround">
|
|
<h3>Workaround<a class="headerlink" href="#workaround" title="Permalink to this headline">¶</a></h3>
|
|
<p>To work around this limitation, one can utilize <a class="reference external" href="https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits/">two phase commits</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="concurrency">
|
|
<h2>Concurrency<a class="headerlink" href="#concurrency" title="Permalink to this headline">¶</a></h2>
|
|
<p>Doctrine MongoDB ODM offers native support for pessimistic and optimistic locking strategies.
|
|
This allows for very fine-grained control over what kind of locking is required for documents in your application.</p>
|
|
<div class="section" id="optimistic-locking">
|
|
<span id="transactions-and-concurrency-optimistic-locking"></span><h3>Optimistic Locking<a class="headerlink" href="#optimistic-locking" title="Permalink to this headline">¶</a></h3>
|
|
<div class="section" id="approach">
|
|
<h4>Approach<a class="headerlink" href="#approach" title="Permalink to this headline">¶</a></h4>
|
|
<p>Doctrine has integrated support for automatic optimistic locking
|
|
via a <code class="docutils literal"><span class="pre">version</span></code> field. Any document that should be
|
|
protected against concurrent modifications during long-running
|
|
business transactions gets a <code class="docutils literal"><span class="pre">version</span></code> field that is either a simple
|
|
number (mapping type: <code class="docutils literal"><span class="pre">int</span></code>) or a date (mapping type: <code class="docutils literal"><span class="pre">date</span></code>).
|
|
When changes to the document are persisted,
|
|
the expected version and version increment are incorporated into the update criteria and modifiers, respectively.
|
|
If this results in no document being modified by the update (i.e. expected version did not match),
|
|
a <code class="docutils literal"><span class="pre">LockException</span></code> is thrown, which indicates that the document was already modified by another query.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<div class="last line-block">
|
|
<div class="line">Versioning can only be used on <em>root</em> (top-level) documents.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="document-configuration">
|
|
<h4>Document Configuration<a class="headerlink" href="#document-configuration" title="Permalink to this headline">¶</a></h4>
|
|
<p>The following example designates a version field using the <code class="docutils literal"><span class="pre">int</span></code> type:</p>
|
|
<div class="configuration-block">
|
|
<ul class="simple">
|
|
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="sd">/** @Version @Field(type="int") */</span>
|
|
<span class="k">private</span> <span class="nv">$version</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="nt"><field</span> <span class="na">fieldName=</span><span class="s">"version"</span> <span class="na">version=</span><span class="s">"true"</span> <span class="na">type=</span><span class="s">"int"</span> <span class="nt">/></span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>YAML</em><div class="highlight-yaml"><div class="highlight"><pre><span class="l l-Scalar l-Scalar-Plain">version</span><span class="p p-Indicator">:</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">int</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">version</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">true</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<p>Alternatively, the <code class="docutils literal"><span class="pre">date</span></code> type may be used:</p>
|
|
<div class="configuration-block">
|
|
<ul class="simple">
|
|
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="sd">/** @Version @Field(type="date") */</span>
|
|
<span class="k">private</span> <span class="nv">$version</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="nt"><field</span> <span class="na">fieldName=</span><span class="s">"version"</span> <span class="na">version=</span><span class="s">"true"</span> <span class="na">type=</span><span class="s">"date"</span> <span class="nt">/></span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>YAML</em><div class="highlight-yaml"><div class="highlight"><pre><span class="l l-Scalar l-Scalar-Plain">version</span><span class="p p-Indicator">:</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">date</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">version</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">true</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="section" id="choosing-the-field-type">
|
|
<h5>Choosing the Field Type<a class="headerlink" href="#choosing-the-field-type" title="Permalink to this headline">¶</a></h5>
|
|
<p>When using the <code class="docutils literal"><span class="pre">date</span></code> type in a high-concurrency environment, it is still possible to create multiple documents
|
|
with the same version and cause a conflict. This can be avoided by using the <code class="docutils literal"><span class="pre">int</span></code> type.</p>
|
|
</div>
|
|
<div class="section" id="usage">
|
|
<h5>Usage<a class="headerlink" href="#usage" title="Permalink to this headline">¶</a></h5>
|
|
<p>When a version conflict is encountered during
|
|
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code>, a <code class="docutils literal"><span class="pre">LockException</span></code> is thrown.
|
|
This exception can be caught and handled. Potential responses to a
|
|
<code class="docutils literal"><span class="pre">LockException</span></code> are to present the conflict to the user or
|
|
to refresh or reload objects and then retry the update.</p>
|
|
<p>With PHP promoting a share-nothing architecture,
|
|
the worst case scenario for a delay between rendering an update form (with existing document data)
|
|
and modifying the document after a form submission may be your application's session timeout.
|
|
If the document is changed within that time frame by some other request,
|
|
it may be preferable to encounter a <code class="docutils literal"><span class="pre">LockException</span></code> when retrieving the document instead of executing the update.</p>
|
|
<p>You can specify the expected version of a document during a query with <code class="docutils literal"><span class="pre">DocumentManager#find()</span></code>:</p>
|
|
<div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\LockMode</span><span class="p">;</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\LockException</span><span class="p">;</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentManager</span><span class="p">;</span>
|
|
|
|
<span class="nv">$theDocumentId</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="nv">$expectedVersion</span> <span class="o">=</span> <span class="mi">184</span><span class="p">;</span>
|
|
|
|
<span class="cm">/* @var $dm DocumentManager */</span>
|
|
|
|
<span class="k">try</span> <span class="p">{</span>
|
|
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="nv">$theDocumentId</span><span class="p">,</span> <span class="nx">LockMode</span><span class="o">::</span><span class="na">OPTIMISTIC</span><span class="p">,</span> <span class="nv">$expectedVersion</span><span class="p">);</span>
|
|
|
|
<span class="c1">// do the work</span>
|
|
|
|
<span class="nv">$dm</span><span class="o">-></span><span class="na">flush</span><span class="p">();</span>
|
|
<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">LockException</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">echo</span> <span class="s2">"Sorry, but someone else has already changed this document. Please apply the changes again!"</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>Alternatively, an expected version may be specified for an existing document with <code class="docutils literal"><span class="pre">DocumentManager#lock()</span></code>:</p>
|
|
<div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\LockMode</span><span class="p">;</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\LockException</span><span class="p">;</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentManager</span><span class="p">;</span>
|
|
|
|
<span class="nv">$theDocumentId</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="nv">$expectedVersion</span> <span class="o">=</span> <span class="mi">184</span><span class="p">;</span>
|
|
|
|
<span class="cm">/* @var $dm DocumentManager */</span>
|
|
|
|
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="nv">$theDocumentId</span><span class="p">);</span>
|
|
|
|
<span class="k">try</span> <span class="p">{</span>
|
|
<span class="c1">// assert version</span>
|
|
<span class="nv">$dm</span><span class="o">-></span><span class="na">lock</span><span class="p">(</span><span class="nv">$document</span><span class="p">,</span> <span class="nx">LockMode</span><span class="o">::</span><span class="na">OPTIMISTIC</span><span class="p">,</span> <span class="nv">$expectedVersion</span><span class="p">);</span>
|
|
|
|
<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">LockException</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">echo</span> <span class="s2">"Sorry, but someone else has already changed this document. Please apply the changes again!"</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="important-implementation-notes">
|
|
<h4>Important Implementation Notes<a class="headerlink" href="#important-implementation-notes" title="Permalink to this headline">¶</a></h4>
|
|
<p>You can easily get the optimistic locking workflow wrong if you
|
|
compare the wrong versions.</p>
|
|
<div class="section" id="workflow">
|
|
<h5>Workflow<a class="headerlink" href="#workflow" title="Permalink to this headline">¶</a></h5>
|
|
<p>Say you have Alice and Bob editing a
|
|
hypothetical blog post:</p>
|
|
<ul class="simple">
|
|
<li>Alice reads the headline of the blog post being "Foo", at
|
|
optimistic lock version 1 (GET Request)</li>
|
|
<li>Bob reads the headline of the blog post being "Foo", at
|
|
optimistic lock version 1 (GET Request)</li>
|
|
<li>Bob updates the headline to "Bar", upgrading the optimistic lock
|
|
version to 2 (POST Request of a Form)</li>
|
|
<li>Alice updates the headline to "Baz", ... (POST Request of a
|
|
Form)</li>
|
|
</ul>
|
|
<p>At the last stage of this scenario the blog post has to be read
|
|
again from the database before Alice's headline can be applied. At
|
|
this point you will want to check if the blog post is still at
|
|
version 1 (which it is not in this scenario).</p>
|
|
<p>In order to correctly utilize optimistic locking, you <em>must</em> add the version as hidden form field or,
|
|
for more security, session attribute.
|
|
Otherwise, you cannot verify that the version at the time of update is the same as what was originally read
|
|
from the database when Alice performed her original GET request for the blog post.
|
|
Without correlating the version across form submissions, the application could lose updates.</p>
|
|
</div>
|
|
<div class="section" id="example-code">
|
|
<h5>Example Code<a class="headerlink" href="#example-code" title="Permalink to this headline">¶</a></h5>
|
|
<p>The form (GET Request):</p>
|
|
<div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentManager</span><span class="p">;</span>
|
|
|
|
<span class="cm">/* @var $dm DocumentManager */</span>
|
|
|
|
<span class="nv">$post</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'BlogPost'</span><span class="p">,</span> <span class="mi">123456</span><span class="p">);</span>
|
|
|
|
<span class="k">echo</span> <span class="s1">'<input type="hidden" name="id" value="'</span> <span class="o">.</span> <span class="nv">$post</span><span class="o">-></span><span class="na">getId</span><span class="p">()</span> <span class="o">.</span> <span class="s1">'" />'</span><span class="p">;</span>
|
|
<span class="k">echo</span> <span class="s1">'<input type="hidden" name="version" value="'</span> <span class="o">.</span> <span class="nv">$post</span><span class="o">-></span><span class="na">getCurrentVersion</span><span class="p">()</span> <span class="o">.</span> <span class="s1">'" />'</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>And the change headline action (POST Request):</p>
|
|
<div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentManager</span><span class="p">;</span>
|
|
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\LockMode</span><span class="p">;</span>
|
|
|
|
<span class="cm">/* @var $dm DocumentManager */</span>
|
|
|
|
<span class="nv">$postId</span> <span class="o">=</span> <span class="p">(</span><span class="nx">int</span><span class="p">)</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'id'</span><span class="p">];</span>
|
|
<span class="nv">$postVersion</span> <span class="o">=</span> <span class="p">(</span><span class="nx">int</span><span class="p">)</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'version'</span><span class="p">];</span>
|
|
|
|
<span class="nv">$post</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'BlogPost'</span><span class="p">,</span> <span class="nv">$postId</span><span class="p">,</span> <span class="nx">LockMode</span><span class="o">::</span><span class="na">OPTIMISTIC</span><span class="p">,</span> <span class="nv">$postVersion</span><span class="p">);</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="pessimistic-locking">
|
|
<span id="transactions-and-concurrency-pessimistic-locking"></span><h3>Pessimistic Locking<a class="headerlink" href="#pessimistic-locking" title="Permalink to this headline">¶</a></h3>
|
|
<p>Doctrine MongoDB ODM also supports pessimistic locking via a configurable <code class="docutils literal"><span class="pre">lock</span></code> field.
|
|
This functionality is implemented entirely by Doctrine; MongoDB has no native support for pessimistic locking.</p>
|
|
<div class="section" id="id1">
|
|
<h4>Document Configuration<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h4>
|
|
<p>Pessimistic locking requires a document to designate a lock field using the <code class="docutils literal"><span class="pre">int</span></code> type:</p>
|
|
<div class="configuration-block">
|
|
<ul class="simple">
|
|
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp"><?php</span>
|
|
<span class="sd">/** @Lock @Field(type="int") */</span>
|
|
<span class="k">private</span> <span class="nv">$lock</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="nt"><field</span> <span class="na">fieldName=</span><span class="s">"lock"</span> <span class="na">lock=</span><span class="s">"true"</span> <span class="na">type=</span><span class="s">"int"</span> <span class="nt">/></span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
<li><em>YAML</em><div class="highlight-yaml"><div class="highlight"><pre><span class="l l-Scalar l-Scalar-Plain">lock</span><span class="p p-Indicator">:</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">int</span>
|
|
<span class="l l-Scalar l-Scalar-Plain">lock</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">true</span>
|
|
</pre></div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="lock-modes">
|
|
<h4>Lock Modes<a class="headerlink" href="#lock-modes" title="Permalink to this headline">¶</a></h4>
|
|
<p>Doctrine MongoDB ODM currently supports two pessimistic lock modes:</p>
|
|
<ul class="simple">
|
|
<li>Pessimistic Write
|
|
(<code class="docutils literal"><span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_WRITE</span></code>): locks the
|
|
underlying document for concurrent read and write operations.</li>
|
|
<li>Pessimistic Read (<code class="docutils literal"><span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_READ</span></code>):
|
|
locks other concurrent requests that attempt to update or lock documents
|
|
in write mode.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="section" id="id2">
|
|
<h4>Usage<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h4>
|
|
<p>You can use pessimistic locks in two different scenarios:</p>
|
|
<ol class="arabic simple">
|
|
<li>Using
|
|
<code class="docutils literal"><span class="pre">DocumentManager#find($className,</span> <span class="pre">$id,</span> <span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_WRITE)</span></code>
|
|
or
|
|
<code class="docutils literal"><span class="pre">DocumentManager#find($className,</span> <span class="pre">$id,</span> <span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_READ)</span></code></li>
|
|
<li>Using
|
|
<code class="docutils literal"><span class="pre">DocumentManager#lock($document,</span> <span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_WRITE)</span></code>
|
|
or
|
|
<code class="docutils literal"><span class="pre">DocumentManager#lock($document,</span> <span class="pre">\Doctrine\ODM\MongoDB\LockMode::PESSIMISTIC_READ)</span></code></li>
|
|
</ol>
|
|
<div class="admonition warning">
|
|
<p class="first admonition-title">Warning</p>
|
|
<div class="last line-block">
|
|
<div class="line">A few things could go wrong:</div>
|
|
<div class="line"><br /></div>
|
|
<div class="line">If a request fails to complete (e.g. unhandled exception), you may end up with stale locks.
|
|
Said locks would need to be manually released or you would need to devise a strategy to automatically do so.
|
|
One way to mitigate stale locks after an application error would be to gracefully catch the exception
|
|
and ensure that relevant documents are unlocked before the request ends.</div>
|
|
<div class="line"><br /></div>
|
|
<div class="line"><a class="reference external" href="https://en.wikipedia.org/wiki/Deadlock">Deadlock</a> situations are also possible.
|
|
Suppose process P1 needs resource R1 and has locked resource R2
|
|
and that another process P2 has locked resource R1 but also needs resource R2.
|
|
If both processes continue waiting for the respective resources, the application will be stuck.
|
|
When loading a document, Doctrine can immediately throw an exception if it is already locked.
|
|
A deadlock could be created by endlessly retrying attempts to acquire the lock.
|
|
One can avoid a possible deadlock by designating a maximum number of retry attempts
|
|
and automatically releasing any active locks with the request ends,
|
|
thereby allowing a process to end gracefully while another completes its task.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="sphinxsidebar">
|
|
<div class="sphinxsidebarwrapper">
|
|
|
|
<div id="searchbox" style="">
|
|
<h3>Search</h3>
|
|
<form class="search" action="http://readthedocs.org/search/project/" method="get">
|
|
<input type="text" name="q" size="18">
|
|
<input type="submit" value="Go">
|
|
<input type="hidden" name="selected_facets" value="project:">
|
|
</form>
|
|
</div>
|
|
<h3><a href="../index.html">Table Of Contents</a></h3>
|
|
<ul>
|
|
<li><a class="reference internal" href="#">Transactions and Concurrency</a><ul>
|
|
<li><a class="reference internal" href="#transactions">Transactions</a><ul>
|
|
<li><a class="reference internal" href="#limitation">Limitation</a></li>
|
|
<li><a class="reference internal" href="#workaround">Workaround</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#concurrency">Concurrency</a><ul>
|
|
<li><a class="reference internal" href="#optimistic-locking">Optimistic Locking</a><ul>
|
|
<li><a class="reference internal" href="#approach">Approach</a></li>
|
|
<li><a class="reference internal" href="#document-configuration">Document Configuration</a><ul>
|
|
<li><a class="reference internal" href="#choosing-the-field-type">Choosing the Field Type</a></li>
|
|
<li><a class="reference internal" href="#usage">Usage</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#important-implementation-notes">Important Implementation Notes</a><ul>
|
|
<li><a class="reference internal" href="#workflow">Workflow</a></li>
|
|
<li><a class="reference internal" href="#example-code">Example Code</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#pessimistic-locking">Pessimistic Locking</a><ul>
|
|
<li><a class="reference internal" href="#id1">Document Configuration</a></li>
|
|
<li><a class="reference internal" href="#lock-modes">Lock Modes</a></li>
|
|
<li><a class="reference internal" href="#id2">Usage</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<h3>This Page</h3>
|
|
<ul class="this-page-menu">
|
|
<li><a href="../_sources/reference/transactions-and-concurrency.rst.txt"
|
|
rel="nofollow">Show Source</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="footer">
|
|
© Copyright 2013, Doctrine Project Team.
|
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.6.2.
|
|
<br/>
|
|
<a target="_BLANK" href="http://www.servergrove.com"><img src="http://www.doctrine-project.org/_static/servergrove.jpg" /></a> <br/><br/>
|
|
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
|
<input type="hidden" name="cmd" value="_s-xclick" />
|
|
<input type="hidden" name="hosted_button_id" value="BAE2E3XANQ77Y" />
|
|
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
|
|
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="bot-rcnr">
|
|
<div class="tl"><!-- corner --></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
|
</script>
|
|
<script type="text/javascript">
|
|
_uacct = "UA-288343-7";
|
|
urchinTracker();
|
|
</script>
|
|
<a class="githublink" href="http://github.com/doctrine"><img src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
|
|
</body>
|
|
</html> |