MongoDB - атомарные операции
Данные модели для атомарных операций
Рекомендуемый подход к поддержанию атомарности - хранить всю связанную информацию, которая часто обновляется вместе в одном документе с использованием embedded documents. Это обеспечит атомарность всех обновлений для одного документа.
Предположим, мы создали коллекцию с именем productDetails и вставили в нее документы, как показано ниже -
>db.createCollection("products")
{ "ok" : 1 }
> db.productDetails.insert(
{
"_id":1,
"product_name": "Samsung S3",
"category": "mobiles",
"product_total": 5,
"product_available": 3,
"product_bought_by": [
{
"customer": "john",
"date": "7-Jan-2014"
},
{
"customer": "mark",
"date": "8-Jan-2014"
}
]
}
)
WriteResult({ "nInserted" : 1 })
>
В этом документе мы встроили информацию о клиенте, который покупает продукт, в product_bought_byполе. Теперь, когда новый клиент покупает продукт, мы сначала проверяем, доступен ли он, используяproduct_availableполе. Если возможно, мы уменьшим значение поля product_available, а также вставим встроенный документ нового клиента в поле product_bought_by. Мы будем использоватьfindAndModify для этой функции, потому что она ищет и обновляет документ одновременно.
>db.products.findAndModify({
query:{_id:2,product_available:{$gt:0}},
update:{
$inc:{product_available:-1},
$push:{product_bought_by:{customer:"rob",date:"9-Jan-2014"}}
}
})
Наш подход встроенного документа и использования запроса findAndModify гарантирует, что информация о покупке продукта обновляется только в том случае, если продукт доступен. И вся эта транзакция, находящаяся в одном запросе, является атомарной.
В отличие от этого, рассмотрим сценарий, в котором мы могли сохранить доступность продукта и информацию о том, кто купил продукт, отдельно. В этом случае мы сначала проверим, доступен ли товар, с помощью первого запроса. Затем во втором запросе мы обновим информацию о покупке. Однако возможно, что между выполнением этих двух запросов какой-то другой пользователь приобрел продукт, и он больше не доступен. Не зная об этом, наш второй запрос обновит информацию о покупке на основе результата нашего первого запроса. Это сделает базу данных несовместимой, потому что мы продали продукт, которого нет в наличии.