|
based on v31 MongoDBのアトミックな操作に対する思想は、従来のデータベースと異なっています。 いくつかの理由から、MongoDBは、従来の方法のロックをサポートしていません。
とは言え、明らかに、ドキュメントの更新をアトミックに行う方法は必要です。このためのいくつかの方法を見てみます。 modifierオペレーションMongoDBのアップデートコマンドは、いくつかの modifier をサポートしています。この操作ではドキュメントのエレメントをアトミックに更新します。次のものがあります。
これらのmodifierは、アトミックな実行をするのに使えます。 "値が変更されていなかったら更新"もう一つの、atomicにアップデートをする戦略として、 "値が変更されていなかったら更新" という方法があります。 これは、
このオペレーションが失敗した場合には、最初のステップからやりなおします。 例えば、一つのオブジェクトをinventoryから取得したいとします。もしそのオブジェクトが存在する場合、取得したinventoryから1引きます。次のコードは、mongoシェルを使いこれをするためのコードです。(どの言語でも同じようなファンクションがあるでしょう) > t=db.inventory
> s = t.findOne({sku:'abc'})
{"_id" : "49df4d3c9664d32c73ea865a" , "sku" : "abc" , "qty" : 30}
> qty_old = s.qty;
> --s.qty;
> t.update({_id:s._id, qty:qty_old}, s); db.$cmd.findOne({getlasterror:1});
{"err" : , "updatedExisting" : true , "n" : 1 , "ok" : 1} // 成功
上記の例では、skuから実際に1引けるかどうかというのを考えていません。そのため下のコードの方が優れていますが汎用性は低いです。 modifierオペレーション ($inc) を使います。一般的なアップデートに関して($incを使えないような)は、上記の"値が変更されていなかったら更新"の方法が推奨されます。 > t.update({sku:"abc",qty:{$gt:0}}, { $inc : { qty : -1 } } ) ; db.$cmd.findOne({getlasterror:1})
{"err" : , "updatedExisting" : true , "n" : 1 , "ok" : 1} // 成功
> t.update({sku:"abcz",qty:{$gt:0}}, { $inc : { qty : -1 } } ) ; db.$cmd.findOne({getlasterror:1})
{"err" : , "updatedExisting" : false , "n" : 0 , "ok" : 1} // 失敗
"存在していなかったらインサート"もう一つの楽観的な並列処理として、存在しない場合だけインサートする、という方法があります。これは、条件に対してユニークインデックスを持っている場合にだけ可能です。次の例は、この方法を使って、_idを単純に増やしながらインサートする例です。
function insertObject(o) {
x = db.myCollection;
while( 1 ) {
// determine next _id value to try
var c = x.find({},{_id:1}).sort({_id:-1}).limit(1);
var i = c.hasNext() ? c.next()._id + 1 : 1;
o._id = i;
x.insert(o);
var err = db.getLastErrorObj();
if( err && err.code ) {
if( err.code == 11000 /* dup key */ )
continue;
else
print("unexpected error inserting data: " + tojson(err));
}
break;
}
}
findしてmodify(またはremove)findandmodifyコマンドドキュメン を参照してください。 複数のオブジェクトをアトミックに更新基本的に、MongoDBは複数のドキュメントを一回の操作でのアトミックな更新をサポートしていません。しかし、アトミック性のために、複数のオブジェクトをネストすることで、1つのオブジェクトにすることができます。 db.eval() 命令は、複数の操作を一度で行うことができます。しかし、eval() のアトミック性は、shard環境のいくつかのケースではサポートされないので、推奨されません。 |

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.
These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group. blog comments powered by Disqus