Предотвращение условий гонки, связанных с базой данных, в Node.js - программирование
Подтвердить что ты не робот

Предотвращение условий гонки, связанных с базой данных, в Node.js

Обзор

Я пытаюсь понять, как обеспечить асинхронную безопасность при использовании экземпляра модели при использовании Node.js. Здесь я использую Mongoose ODM в образцах кода, но этот вопрос применим ко всем случаям, когда база данных используется с асинхронным подходом ввода-вывода, основанным на событиях, который использует Node.js.

Рассмотрим следующий код (который использует запросы Mongoose для MongoDB):

Фрагмент A

MyModel.findOne( { _id : <id #1> }, function( err, doc ) {
    MyOtherModel.findOne( { _id : someOtherId }, ( function(err, otherDoc ) {
        if (doc.field1 === otherDoc.otherField) {
            doc.field2 = 0; // assign some new value to a field on the model
        }
        doc.save( function() { console.log( 'success' ); }
    });
});

В отдельной части приложения документ, описанный MyModel, может быть обновлен. Рассмотрим следующий код:

Фрагмент B

MyModel.update( { _id : <id #1> }, { $set : { field1 : someValue }, callback );

В Snippet A запрос MongoDB выдается с зарегистрированным обратным вызовом, который должен быть запущен, как только документ будет готов. Экземпляр документа, описанный MyModel, сохраняется в памяти (в объекте doc). Возможна следующая последовательность:

  • Фрагмент A выполняется
  • Для MyModel инициируется запрос, регистрирующий обратный вызов (обратный вызов A) для последующего использования
  • < < Цикл событий Node запускается →
  • MyModel извлекается из базы данных, выполняя зарегистрированный обратный вызов (обратный вызов A)
  • Для MyOtherModel инициируется запрос, регистрирующий обратный вызов для последующего использования (обратный вызов B)
  • < < Цикл событий Node запускается →
  • Фрагмент B выполняется
  • Обновлен документ (id # 1)
  • < < Цикл событий Node запускается →
  • MyOtherModel извлекается из базы данных, выполняя зарегистрированный обратный вызов (обратный вызов B)
  • В сравнении неверно используется устаревшая версия документа (id # 1).

Вопросы

  • Есть ли какие-либо гарантии, что такого рода состояние гонки не произойдет в Node.js/MongoDB?
  • Что я могу сделать, чтобы детерминистически предотвратить этот сценарий?

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

4b9b3361

Ответ 1

Нет, нет никаких гарантий того, что этот тип расы не будет происходить в node.js/MongoDB. Однако это не имеет никакого отношения к node.js, и это возможно с любой базой данных, поддерживающей параллельный доступ, а не только с MongoDB.

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