Гарантии записи

MongoDB предоставляет несколько различных способов выбора, как будет проходить запись в базу данных. Эти способы называются гарантии записи и охватывают все: от полного игнорирования всех ошибок до определения того, какие серверы должны подтвердить запись перед возвратом операции.

Когда для записи (например, с помощью MongoCollection::insert(), MongoCollection::update() и MongoCollection::remove()) задаётся параметр гарантий записи ("w"), драйвер отправляет запрос в MongoDB и piggy возвращает команду getLastError (GLE) одновременно с опцией гарантии записи. Сервер возвращает только в том случае, если условие гарантий записи прошло проверку, как выполненное или время ожидания запроса истекло (с параметром "wtimeout" по умолчанию установлено значение 10000 миллисекунд).

Внимание

Несмотря на то, что время ожидания команды getLastError истекло, данные, скорее всего, будут записаны на основной сервер и реплицированы на все вторичные серверы, как только они его догонят.

Типичные причины возникновения превышения времени ожидания - указание записи о проблеме, которая требует подтверждения с большего количества серверов, чем доступно в данный момент.

При использовании подтверждённых записей и сбоя набора реплик, драйвер автоматически отключается от основного сервера, выдаёт исключение и пытается найти новый основной на следующей операции (ваше приложение должно решить, следует ли повторить операцию на новый основной сервер).

При использовании неподтверждённых записей (w=0) и при сбое набора реплик, драйвер не сможет узнать об изменении, поэтому он продолжит работу и молча прекратит запись.

Гарантии записи по умолчанию для MongoClient1: подтверждение операций записи.

Доступные гарантии записи
Гарантии записи Значение Описание
w=0 Не подтверждён За записью не последует вызов GLE, поэтому она не проверяется ("выстрели и забудь")
w=1 Подтверждён Запись будет подтверждена сервером (основной в конфигурации набора реплик)
w=N Набор реплик подтверждён Запись будет подтверждена основным сервером и реплицирована на N-1 вторичных серверов.
w=majority Подтверждён большинством Запись будет подтверждена большинством наборов реплик (включая основной). Это специальная зарезервированная строка.
w=<tag set> Набор меток для набора реплик подтверждён Запись будет подтверждена всеми членами набора меток.
j=true Журналируемый Запись будет подтверждена первичным сервером и журнал будет записан на диск

Использование гарантий записи

Каждый из методов, вызывающих запись (MongoCollection::insert(), MongoCollection::update(), MongoCollection::remove() и MongoCollection::batchInsert()), позволяет использовать необязательный аргумент для отправки набора параметров в MongoDB сервер. С этим массивом опций вы можете установить гарантии записи, как показано в следующем примере:

Пример #1 Передача гарантий записи в запись

<?php
// Устанавливаем w=0 для insert:
$collection->insert($someDoc, array("w" => 0));

// Устанавливаем w=majority для update:
$collection->update($someDoc$someUpdates, array("w" => "majority"));

// Устанавливаем w=5 и j=true для remove:
$collection->remove($someDoc, array("w" => 5"j" => true));

// Устанавливаем w="AllDCs" для batchInsert:
$collection->batchInsert(array($someDoc1$someDoc2), array("w" => "AllDCs"));
?>

Помимо установки гарантий записи для каждой операции в качестве аргумента опции, также можно установить гарантии записи по умолчанию различными способами.

Первый способ - через строку подключения. Строка подключения принимает параметры journal, w и wTimeoutMS:

Пример #2 Гарантии записи в строке подключения

<?php
$m 
= new MongoClient("mongodb://localhost/?journal=true&w=majority&wTimeoutMS=20000");
?>

Начиная с версии 1.5 драйвера также можно вызывать MongoDB::setWriteConcern() и MongoCollection::setWriteConcern(), чтобы установить гарантии записи по умолчанию для всех операций, созданных из этого конкретного объекта MongoDB или MongoCollection:

Пример #3 MongoDB::setWriteConcern и MongoCollection::setWriteConcern

<?php
$m 
= new MongoClient("mongodb://localhost/");
$d $m->demoDb;
$c $d->demoCollection;

// Устанавливаем w=3 на объекте базы данных с таймаутом 25000 мс
$d->setWriteConcern(325000);

// Устанавливаем w=majority на объекте коллекции без изменения времени ожидания
$c->setWriteConcern("majority");
?>

Неподтверждённые записи

Не требуя от сервера подтверждения записи, запись может быть выполнена очень быстро, но вы не будете знать, действительно ли запись удалась. Запись может завершиться неудачей по ряду причин: если есть проблемы с сетью, если сервер базы данных вышел из строя, или если запись была просто недействительной (например, запись в системную коллекцию или ошибки дублированного ключа).

При разработке всегда следует использовать подтверждённые записи (для защиты от непреднамеренных ошибок, таких как синтаксические ошибки, недопустимые операторы, ошибки дублирующихся ключей и т.д.). В производстве неподтверждённые записи могут использоваться для "незначительных" данных. Незначительные данные различаются в зависимости от приложения, но, как правило, это автоматические (вместо сгенерированных пользователем) данные, таких как отслеживание кликов или местоположения GPS, где вы можете получать тысячи записей в секунду.

Настоятельно рекомендуется выполнять подтверждённую запись в конце серии неподтверждённых записей. Это не приведёт к слишком большим потерям производительности, но всё же позволит вам отследить любые ошибки, которые могли произойти.

Пример #4 Неподтверждённые гарантии записи, сопровождаемые подтверждением записи

<?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) {
    
/* Обрабатываем исключение.. */
    /* Здесь мы должны выполнить запросы find() по идентификаторам,
    сгенерированным для $thingElse и $someDoc, чтобы убедиться,
    что они записаны в базу данных, и попытаться выяснить, где в цепочке что-то произошло */
}
?>

Если последняя запись выдаёт исключение, вы будете знать, что есть проблема с вашей базой данных.

Подтверждённые записи

Этот тип операций записи гарантирует, что база данных приняла операцию записи, прежде чем вернуть успешное выполнение. Если запись не удалась, она выдаст исключение MongoCursorException с объяснением ошибки. Поведение MongoClient по умолчанию - подтверждение записи (w=1).

Можно указать, сколько членов набора реплик должно подтвердить запись (т.е. реплицировать ли её) до того, как запись будет признана подтверждённой и операция вернёт успешное выполнение.

Пример #5 Подтверждённые записи

<?php
// Принудительное подтверждение только от основного сервера
$collection->insert($doc, array("w" => 1));

// Принудительное подтверждение от основного и ещё одного
// члена набора реплик
$collection->insert($doc, array("w" => 2));

// Принудительное подтверждение от основного и шести других
// членов набора реплик (вы, вероятно, никогда не должны делать так):
$collection->insert($doc, array("w" => 7));
?>

Имейте в виду, необходимо тщательно выбирать ваши гарантии записи. Если у вас есть набор реплик с 5 участниками, и вы выбираете гарантии записи 4, вы рискуете заблокировать запись навсегда, когда один из членов набора реплик выйдет из строя на техническое обслуживание или произойдёт временное отключение сети.

Внимание

Передача строкового значения для гарантий записи имеет особое значение (Набор меток для набора реплик подтверждён). Пожалуйста, будьте осторожны, НЕ используйте строковые значения для чисел (т.е. array("w" => "1")), так как он будет рассматриваться, как имя набора тегов.

Записи, подтверждённые большинством

Использование особой опции majority гарантий записи - это рекомендуемый способ записи, необходимый для выживания после апокалипсиса, поскольку он гарантирует, что большая часть вашего набора реплик будет иметь запись и, следовательно, будет гарантированно выдерживать все обычные сценарии подозрительных сбоев.

Пример #6 Записи, подтверждённые большинством

<?php
$collection
->insert($someDoc, array("w" => "majority"));
?>

Журналируемые записи

При подключении к реплике задайте гарантии записи по умолчанию только для того, чтобы основной сервер подтвердил запись. Однако существует окно 100 мс, пока запись не будет занесена в журнал и записана на диск. Можно принудительно записать запись в журнал перед подтверждением записи, установив опцию j:

Пример #7 Подтверждённые и журналируемые записи

Принудительное заполнение журнала

<?php
$options 
= array(
    
"w" => 1,
    
"j" => true,
);
try {
    
$collection->insert($document$options);
} catch(
MongoCursorException $e) {
    
/* обрабатываем исключение */
}
?>

Список изменений

Версия Описание
1.3.0 В MongoClient были введены по умолчанию подтверждённые записи. Устаревшим значением по умолчанию в Mongo были неподтверждённые записи.
1.3.0 Опция "safe" записи устарела и недоступна для нового класса MongoClient. Вместо этого используйте опцию "w".
add a note add a note

User Contributed Notes 1 note

up
0
mikec
6 years ago
Warning

Even though a getLastError 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.

**caught up
To Top