我有一个带有集合cA,cB和cC的数据库。我需要以事务方式每5分钟更新一次数据库(cB是cA和cC的n-m关系)。由于模拟transactions with mongo似乎并不容易,我可以在开始上传过程之前创建cA,cB和cC的快照(db.cA.copyTo(“cA_snapshot”))并翻转阅读查询在执行插入时的快照上。不幸的是,集合大小总计超过8Gb并且正在进行集合。复制似乎需要太长时间。
那么,有没有办法通过日记实现这一目标?假设我在启动时花费一次创建集合的快照。之后,我可以手动重播cA_snapshot上cA的日记项吗?
谢谢
答案 0 :(得分:0)
如果您在更新“连接表”时愿意锁定所有三个集合的所有更新,则可以通过应用程序级锁定来实现此更新。
简短版本:您创建'locks'集合。在更新cA,cB或cC三个集合中的任何一个之前,每个客户端都必须获得“写锁定”。它通过更新'locks'集合中的文档来实现。当您准备好执行批量更新时,您将获得“写入锁定”,执行更新并释放锁定。
这是一些实现锁定的简单示例代码。请注意,此代码有几个限制:
修复这些限制留给读者练习。
XDB = db.mylocks;
/*
* Set up the locking collection
*/
function setup_locking( res_name ) {
var doc = { _id: res_name, state: "UNLOCKED", locker: null };
// upsert to create document if it does not exist
XDB.update( {id: res_name}, doc, true );
}
/*
* Lock the resource named 'res_name' by process named 'proc'
*
* Returns 'true' if resource was acquired, 'false' if it was not acquired
*/
function lockit( res_name, proc ) {
/*
* 1) Change state to LOCKED if & only if it was previously UNLOCKED
*/
ret = XDB.findAndModify( {
query: { _id:res_name, state:"UNLOCKED" } ,
update: {"$set": { state:"LOCKED", locker: proc } },
fields: { state:1, locker:1 },
new: true
}
);
/*
* Return 'true' if this process acquired this resource
*/
if ( ret && (ret.state == "LOCKED") && (ret.locker == proc) )return true;
/*
* 2) Failed to acquire this resource
*/
return false;
}
/*
* Unlock the resource named 'res_name' previously held by 'proc'
*/
function unlockit( res_name, proc ) {
// Unlock resource if this process had previously acquired it
XDB.findAndModify( {
query: { _id:res_name, locker: proc, state:"LOCKED" } ,
update: {"$set": { state:"UNLOCKED", locker: null } },
}
);
}
/*
* Check to see if resource 'res_name' is currently held by 'proc'
*/
function has_lock( res_name, proc ) {
res = XDB.findOne({_id: res_name, locker:proc} );
if (res == null) return false;
return true;
}
XDB.drop();
setup_locking('collectionA');
result = lockit( 'collectionA', 'app1');
print("1: result =", result);
result = lockit( 'collectionA', 'app2');
print("2: result =", result);
result = lockit( 'collectionA', 'app1');
print("3a: result =", result);
result = has_lock( 'collectionA', 'app1');
print("3b: result =", result);
result = has_lock( 'collectionA', 'app2');
print("3c: result =", result);
unlockit( 'collectionA', 'app1');
result = lockit( 'collectionA', 'app2');
print("4: result =", result);