Транзакции в MongoDB
Имеется коллекция в MongoDB в которой хранятся данные об обработке данных expressjs сервером .
Так как обработка происходит асинхронно, а целостность этих данных очень важна я пришел к использованию транзакций. Драйвером MongoDB в моем случае выступает mongoose. Код примерно таков (он упрощен и не имеет некоторых валидаций):
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const Schema = new mongoose.Schema({
id: Number,
name: String
}, {
autoCreate: true
});
const Data = mongoose.model('Data', Schema );
app.get('/', function (req, res) {
if(req.query.id && req.query.name) {
//Начало сессии
const session = await Data.startSession();
//Запуск транзакции
session.startTransaction();
try {
//Поиск уже существующей записи
const exits = await Data.findOne({id: req.query.id, name: req.query.name}).session(session);
if (exits === null) {//Если ее нет, то создаем
await Data({id: req.query.id, name: req.query.name}).save({session});
}
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
session.endSession();
console.log(error)
} finally {
session.endSession();
}
}
res.send('ok')
})
app.listen(3000)
Гарантирует ли такой подход исключение ситуации с асинхронным выполнением двух транзакций когда поступает 2 одинаковых запроса и когда (как это было бы при операциях без транзакции):
- Запрос #1 Делает запрос на проверку существования | Запрос #2 уже ранее сделал запрос, но не сделал insert
- Запрос #1 Проверил на существование и понял что записи еще нет | Запрос #2 Все еще не сделал insert
- Запрос #1 Делает insert | Запрос #2 Делает insert
- В базе имеется 2 экземпляра одной записи
Если подход с транзакциями это исключит, тогда вопрос. Транзакции выполняются по очереди и до завершения активной транзакции коллекция не может быть модифицирована из вне?
Если одна транзакция выполнится, получается что вторая так же выполнится успешно проверив на существование, и так как запись будет уже добавлена первой транзакцией, то просто не добавит новую?
Обязательно ли делать session.commitTransaction(); если я не делал изменений в базе и только делал из нее выборки (случай когда exits !== null)