mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-27 06:18:56 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@330401 c90b9560-bf6c-de11-be94-00142212c4b1
411 lines
14 KiB
XML
411 lines
14 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
|
|
<chapter xml:id="mongo.writeconcerns" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Write Concerns</title>
|
|
|
|
<para>
|
|
MongoDB provides several different ways of selecting how durable a write to
|
|
the database should be. These ways are called <literal>Write
|
|
Concerns</literal> and span everything from completely ignoring all errors,
|
|
to specifically targetting which servers are required to confirm the write
|
|
before returning the operation.
|
|
</para>
|
|
<para>
|
|
When a write (such as with <methodname>MongoCollection::insert</methodname>,
|
|
<methodname>MongoCollection::update</methodname>, and
|
|
<methodname>MongoCollection::remove</methodname>) is given a Write Concern
|
|
option (<literal>"w"</literal>) the driver will send the query to MongoDB
|
|
and piggy back a <literal>getLastError</literal> command
|
|
(<acronym>GLE</acronym>) with the Write Concern option at the same time.
|
|
The server only returns when the Write Concern condition is verified to be
|
|
fullfilled, or the query times out (controlled with the
|
|
<literal>"wtimeout"</literal> option, <literal>10000</literal> milliseconds
|
|
is the default).
|
|
</para>
|
|
|
|
<warning>
|
|
<para>
|
|
Even though a <literal>getLastError</literal> command times out the data
|
|
will most likely have been written to the primary server and will be
|
|
replicated to all the secondaries once they have cought up.
|
|
</para>
|
|
<para>
|
|
The typical reasons for a timeout to happen is if you specify a Write
|
|
Concern which requires confirmation from more servers then you currently
|
|
have available.
|
|
</para>
|
|
</warning>
|
|
|
|
<para>
|
|
When using acknowledged writes and the replica set has failed over, the driver
|
|
will automatically disconnect from the primary, throw an exception, and
|
|
attempt to find a new primary on the next operation (your application must
|
|
decide whether or not to retry the operation on the new primary).
|
|
</para>
|
|
<para>
|
|
When using unacknowledged writes (w=0) and the replica set has failed over,
|
|
there will be no way for the driver to know about the change so it will
|
|
continue and silently fail to write.
|
|
</para>
|
|
<para>
|
|
The default Write Concern for the <classname>MongoClient</classname> is
|
|
<literal>1</literal>: acknowledge write operations.
|
|
</para>
|
|
|
|
|
|
<para>
|
|
<table xml:id="mongo.writeconcerns.options">
|
|
<title>Available Write Concerns</title>
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry>Write Concern</entry>
|
|
<entry>Meaning</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<!--
|
|
<row>
|
|
<entry>w=-1</entry>
|
|
<entry>Errors ignored</entry>
|
|
<entry>No errors, including network errors, will be checked at all</entry>
|
|
</row>
|
|
-->
|
|
<row>
|
|
<entry>w=0</entry>
|
|
<entry>Unacknowledged</entry>
|
|
<entry>A write will not be followed up with a <acronym>GLE</acronym> call, and therefore not checked ("fire and forget")</entry>
|
|
</row>
|
|
<row>
|
|
<entry>w=1</entry>
|
|
<entry>Acknowledged</entry>
|
|
<entry>The write will be acknowledged by the server (the primary on replica set configuration)</entry>
|
|
</row>
|
|
<row>
|
|
<entry>w=N</entry>
|
|
<entry>Replica Set Acknowledged</entry>
|
|
<entry>The write will be acknowledged by the primary server, and
|
|
replicated to <literal>N-1</literal> secondaries.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>w=majority</entry>
|
|
<entry>Majority Acknowledged</entry>
|
|
<entry>The write will be acknowledged by the majority of the replica set (including the primary). This is a special reserved string.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>w=<tag set></entry>
|
|
<entry>Replica Set Tag Set Acknowledged</entry>
|
|
<entry>The write will be acknowledged by members of the entire tag set</entry>
|
|
</row>
|
|
<row>
|
|
<entry>j=true</entry>
|
|
<entry>Journaled</entry>
|
|
<entry>The write will be acknowledged by primary and the journal flushed to disk</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
|
|
<simplesect xml:id="mongo.writeconcerns.setting">
|
|
<title>Using WriteConcerns</title>
|
|
<para>
|
|
Each of the methods that causes writes
|
|
(<methodname>MongoCollection::insert</methodname>,
|
|
<methodname>MongoCollection::update</methodname>,
|
|
<methodname>MongoCollection::remove</methodname>, and
|
|
<methodname>MongoCollection::batchInsert</methodname>) allow an optional
|
|
argument to send a set of options to the MongoDB server. With this option
|
|
array you can set the WriteConcern as the following example illustrates:
|
|
</para>
|
|
<example>
|
|
<title>Passing a WriteConcern to a write operation</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Setting w=0 for insert:
|
|
$collection->insert($someDoc, array("w" => 0));
|
|
|
|
// Setting w=majority for update:
|
|
$collection->update($someDoc, $someUpdates, array("w" => "majority"));
|
|
|
|
// Setting w=5 and j=true for remove:
|
|
$collection->update($someDoc, array("w" => 5, "j" => true));
|
|
|
|
// Setting w="AllDCs" for batchInsert:
|
|
$collection->update(array($someDoc1, $someDoc2), array("w" => "AllDCs"));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Besides setting WriteConcerns per operation as an option argument, it is
|
|
also possible to set a default WriteConcern in different ways.
|
|
</para>
|
|
<para>
|
|
The first way is through the <link
|
|
linkend="mongo.mongoclient.construct.parameters">connection
|
|
string</link>. The connection string accepts the
|
|
<literal>journal</literal>, <literal>w</literal>, and
|
|
<literal>wTimeoutMS</literal> options:
|
|
</para>
|
|
<example>
|
|
<title>Connection string WriteConcerns</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$m = new MongoClient("mongodb://localhost/?journal=true&w=majority&wTimeoutMS=20000");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Since driver version 1.5 it is also possible to call
|
|
<methodname>MongoDB::setWriteConcern</methodname> and
|
|
<methodname>MongoCollection::setWriteConcern</methodname> to set a default
|
|
WriteConcern for all operations created from that specific
|
|
<classname>MongoDB</classname> or <classname>MongoCollection</classname>
|
|
object:
|
|
</para>
|
|
<example>
|
|
<title>MongoDB::setWriteConcern and MongoCollection::setWriteConcern</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$m = new MongoClient("mongodb://localhost/");
|
|
$d = $m->demoDb;
|
|
$c = $d->demoCollection;
|
|
|
|
// Set w=3 on the database object with a timeout of 25000ms
|
|
$d->setWriteConcern(3, 25000);
|
|
|
|
// Set w=majority on the collection object without changing the timeout
|
|
$c->setWriteConcern("majority");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.writeconcerns.unacknowledged">
|
|
<title>Unacknowledged Writes</title>
|
|
<para>
|
|
By not requiring the server to acknowledge writes the writes can be performed
|
|
extremely quickly, but you don't know whether or not they actually succeeded.
|
|
Writes can fail for a number of reasons: if there are network problems, if a
|
|
database server goes down, or if the write was simply invalid (e.g., writing
|
|
to a system collection; or duplicate key errors).
|
|
</para>
|
|
<para>
|
|
While developing, you should always use acknowledged writes (to protect against
|
|
inadvertent mistakes, such as syntax errors, invalid operators, duplicate key errors and so on). In
|
|
production, unacknowledged writes can be used for "unimportant" data. Unimportant
|
|
data varies on application, but it's generally automatically (instead of user
|
|
generated) data, such as click tracking or GPS locations, where you can get
|
|
thousands of records per second.
|
|
</para>
|
|
<para>
|
|
It is strongly recommended that you do an acknowledged write at the end of
|
|
series of unacknowledged writes. Doing so will not incur in a too large
|
|
performance penalty, but still allow you to catch any errors that may have
|
|
occurred.
|
|
</para>
|
|
<example xml:id="mongo.writeconcerns.unacknowledged-example">
|
|
<title>Unacknowledged WriteConcern, followed with Acknowledged Write</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$collection->insert($someDoc, array("w" => 0));
|
|
$collection->update($criteria, $newObj, array("w" => 0));
|
|
$collection->insert($somethingElse, array("w" => 0));
|
|
try {
|
|
$collection->remove($something, array("w" => 1));
|
|
} catch(MongoCursorException $e) {
|
|
/* Handle the exception.. */
|
|
/* Here we should issue find() queries on the IDs generated for
|
|
$somethingElse and $someDoc to verify they got written to the database and
|
|
attempt to figureout where in the chain something happened. */
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
If the last write throws an exception, you know that there's a problem
|
|
with your database.
|
|
</para>
|
|
</example>
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.writeconcerns.acknowledged">
|
|
<title>Acknowledged Writes</title>
|
|
<para>
|
|
These type of write operations will make sure that the database has
|
|
accepted the write operation before returning success. If the write failed,
|
|
it will throw a <classname>MongoCursorException</classname> with an
|
|
explanation of the failure. The <classname>MongoClient</classname> default
|
|
behaviour is to acknowledge the write (w=1).
|
|
</para>
|
|
<para>
|
|
It is possible to specify how many members of an replica set have to
|
|
acknowledge the write (i.e. have it replicated) before the write is deemed
|
|
acknowledged and the operation returns.
|
|
<example xml:id="mongo.writeconcerns.acknowledged-example">
|
|
<title>Acknowledged Writes</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Force acknowledgement from the primary only
|
|
$collection->insert($doc, array("w" => 1));
|
|
|
|
// Force acknowledgement from the primary, and one other member of the
|
|
// replica set
|
|
$collection->insert($doc, array("w" => 2));
|
|
|
|
// Force acknowledgement from the primary, and six other members of the
|
|
// replica set (you probably never should do this):
|
|
$collection->insert($doc, array("w" => 7));
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
Keep in mind to select your Write Concern carefully. If you have a
|
|
replica set with 5 members, and you select Write Concern of
|
|
<literal>4</literal> you will risk the write blocking forever when one
|
|
member of the replica set goes down for maintenance or a temporary network
|
|
outage happens.
|
|
</para>
|
|
</example>
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
Passing in a string value for Write Concern has a specific meaning
|
|
(Replica Set Tag Set Acknowledged). Please be careful of
|
|
<emphasis>NOT</emphasis> using string values for numbers (i.e.
|
|
<literal>array("w" => "1")</literal>) as it will be treated as a tag set
|
|
name.
|
|
</para>
|
|
</warning>
|
|
</simplesect>
|
|
|
|
<simplesect xml:id="mongo.writeconcerns.majority.acknowledged">
|
|
<title>Majority Acknowledged Writes</title>
|
|
<para>
|
|
Using the special <literal>majority</literal> Write Concern option is the
|
|
recommended way for writes that are required to survive the apocalypse, as
|
|
it will ensure the majority of your replica set will have the write and will
|
|
therefore be guaranteed to survive all usual suspect outage scenarios.
|
|
</para>
|
|
<example xml:id="mongo.writeconcerns.majority.acknowledged-example">
|
|
<title>Majority Acknowledged Write</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$collection->insert($someDoc, array("w" => "majority"));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</simplesect>
|
|
|
|
<!-- FIXME
|
|
<simplesect xml:id="mongo.writeconcerns.tagset">
|
|
<title>ReplicaSet TagSet Acknowledged</title>
|
|
</simplesect>
|
|
-->
|
|
|
|
<simplesect xml:id="mongo.writeconcerns.journal">
|
|
<title>Journaled Writes</title>
|
|
<para>
|
|
When connecting to a replica set the default Write Concern is only to have
|
|
the primary server acknowledge the write. There is however a 100ms window
|
|
until the write gets journaled and flushed to disk. It is possible to force
|
|
the write to be journaled before acknowledging the write by setting the
|
|
<literal>j</literal> option:
|
|
<example xml:id="mongo.writeconcerns.journalled">
|
|
<title>Acknowledged and Journaled Write</title>
|
|
<para>Forcing journal flush</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$options = array(
|
|
"w" => 1,
|
|
"j" => true,
|
|
);
|
|
try {
|
|
$collection->insert($document, $options);
|
|
} catch(MongoCursorException $e) {
|
|
/* handle the exception */
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</simplesect>
|
|
|
|
<simplesect role="seealso">
|
|
&reftitle.seealso;
|
|
<simplelist>
|
|
<member>
|
|
<link xlink:href="&url.mongodb.docs;applications/replication/#replica-set-write-concern">MongoDB WriteConcern docs</link>
|
|
</member>
|
|
</simplelist>
|
|
</simplesect>
|
|
|
|
<simplesect role="changelog">
|
|
&reftitle.changelog;
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>1.3.0</entry>
|
|
<entry>
|
|
<classname>MongoClient</classname> was introduced and defaults to
|
|
<link linkend="mongo.writeconcerns.acknowledged">acknowledged</link> writes.
|
|
The deprecated <classname>Mongo</classname> defaults to unacknowledged
|
|
writes.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1.3.0</entry>
|
|
<entry>
|
|
The <literal>"safe"</literal> write option has been deprecated and is
|
|
not available with the new <classname>MongoClient</classname> class.
|
|
Use the <literal>"w"</literal> option instead.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</simplesect>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|
|
|