这可能是一个不同的坏主意,或者我们必须解决数据库并发问题的可能解决方案。
我们有一个方法被调用来更新 mongo 记录。我们看到了一些并发问题 - 进程 A 读取记录,进程 B 读取记录,进程 A 修改并保存记录,进程 B 修改并保存记录。因为 B 在 A 之后读取,在 A 写入之前,它不知道 A 所做的更改,因此我们丢失了来自 A 的数据。
我想知道我们是否不能使用数据库信号量,基本上是集合上的一个字段,它是一个布尔值。如果我们在方法开始时读取记录,并且该字段为真,则它正在被编辑。此时,使用 process.nexttick() 使用相同的数据重新调用该方法。否则,设置信号量,然后继续。
读取和保存之间仍有一些时间,但它应该/可能比我们现在正在做的更快。
变成这样。有什么想法,有人做过这样的事吗?它甚至会起作用吗?
function remove_source(service_id,session, next)
{
var User = Mongoose.model("User");
/* get the user, based on the session user id */
User.findById(session.me,function(err,user_info)
{
if (user_info.semaphore === true)
{
process.nextTick(remove_source(service_id,session,next));
}
else
{
user_info.semaphore = true;
user_info.save(function(err,user_new)
{
if (err) next(err,user_new);
else continue_on(null,user_new);
});
}
function continue_on(user_new)
{
etc.......
}
编辑:新代码:
该函数现在如下所示。我正在对数组进行单独更新。这当然意味着,如果在第一个和第二个事务之间的事务失败,我现在有可能使数据不同步。我在想我可以简单地重新保存我在进入函数时检索到的用户对象,覆盖我的更改。如果我没有更改该对象,我不知道 Mongoose/Mongo 是否不会进行保存,将不得不尝试看看。还有什么想法吗?
var User = Mongoose.model("User");
/* get the user, based on the session user id */
User.findById(session.me,function(err,user_info)
{
if (err)
{
next(err,user_info,null);
return;
}
if (!user_info || user_info.length === 0)
{
next(_e("ACCOUNT_NOT_FOUND"),"user_id: " + session.me);
return;
}
var source_service_info = _.where(user_info.credentials, {"source_service_id": service_id});
var source_service = source_service_info.source_service;
User.findByIdAndUpdate(session.me,{$pull: {"credentials": {"source_service_id": service_id}}},{},function(err,user_credential_removed)
{
if (err)
{
next(err,user_info,null);
return;
}
User.findByIdAndUpdate(session.me,{$pull: {"criteria": {"source_service": source_service}}},{},function(err,user_criteria_removed)
{
if (err)
{
next(err,user_info,null);
return;
}
else
{
next(null,user_criteria_removed);
}
});
});
});
};