在mongodb中同时写入
问题描述:
当我在集合中插入/更新文档时,锁是应用于数据库还是集合。假设我有两个集合,并且它们在同一个数据库中彼此独立,并且想要同时对它们执行写操作。这可能吗?在mongodb中同时写入
这里是我使用来测试这个代码:
var assert = require('assert'),
MongoClient = require('mongodb').MongoClient,
async = require('async');
var station_list = require('./station_list.json'),
trains_list = require('./trains_list.json');
var stationList = [],
trainsList = [];
var MONGO_URL = 'mongodb://localhost:27017/test';
for(var i=0; i<station_list.stations.length; i++)
stationList.push(station_list.stations[i].station_code);
for(var i=0; i<trains_list.trains.length; i++)
trainsList.push(trains_list.trains[i].code);
console.log('trains : ' + trainsList.length + ' stations : ' + stationList.length);
populateTrains();
populateStations();
function populateTrains() {
async.eachSeries(trainsList, populateTrainDb, function (err) {
assert.equal(null, err);
});
}
function populateTrainDb(code, callback) {
MongoClient.connect(MONGO_URL, function (err, db) {
assert.equal(null, err);
var jsonData = {};
jsonData.code = code;
db.collection('trainsCon').replaceOne(
{'code' : code}, jsonData, {upsert: true, w:1}, function (err, res) {
assert.equal(null, err);
db.close();
callback();
});
});
}
function populateStations() {
async.eachSeries(stationList, populateStationDb, function (err) {
assert.equal(null, err);
});
}
function populateStationDb(code, callback) {
MongoClient.connect(MONGO_URL, function (err, db) {
assert.equal(null, err);
var jsonData = {};
jsonData.code = code;
db.collection('stationsCon').replaceOne(
{'code' : code}, jsonData, {upsert:true, w:1}, function (err, res) {
assert.equal(null, err);
db.close();
callback();
});
});
}
两个JSON文件:station_list.json和trains_list.json有大约5000个条目。所以在运行给定程序后,我得到这个错误了一段时间后:
C:\Users\Adnaan\Desktop\hopSmart\node_modules\mongodb\lib\server.js:242
process.nextTick(function() { throw err; })
^
AssertionError: null == { [MongoError: connect EADDRINUSE 127.0.0.1:27017]
name: 'MongoError',
message: 'connect EADDRINUSE 127.0.0.1:27017' }
at C:\Users\Adnaan\Desktop\hopSmart\testing.js:52:10
at C:\Users\Adnaan\Desktop\hopSmart\node_modules\mongodb\lib\mongo_client.js:276:20
at C:\Users\Adnaan\Desktop\hopSmart\node_modules\mongodb\lib\db.js:224:14
at null.<anonymous> (C:\Users\Adnaan\Desktop\hopSmart\node_modules\mongodb\lib\server.js:240:9)
at g (events.js:273:16)
at emitTwo (events.js:100:13)
at emit (events.js:185:7)
at null.<anonymous> (C:\Users\Adnaan\Desktop\hopSmart\node_modules\mongodb-core\lib\topologies\server.js:301:68)
at emitTwo (events.js:100:13)
at emit (events.js:185:7)
当我检查条目的数量进入了数据库,约4000项已经在这两个集合输入。所以我从上面的实验中得到的结果是,当一次写入正在尝试时,可能发生了错误,而在其他收集中,文档必须已经被写入。
那么我应该如何继续进行这种并发性而没有冲突的锁。
答
这个问题的答案可能很长,取决于各种因素(MongoDB版本,存储引擎,正在进行的操作类型,分片等)。我只能建议您仔细阅读MongoDB文档的Concurrency部分,特别是lock granularity part。
确保首先选择正确版本的MongoDB,因为每个版本的行为差别很大(例如3.0版之前的数据库锁定与3.0版之后的使用NMAPv1的大多数操作的集合锁定)。
答
我不认为这是MongoDB的并发问题,但我可能是驱动程序,甚至是测试本身。 几周前我创建了一个示例应用程序来强调测试MongoDB,同时处理一个讨厌的bug。我在Windows 10上使用了C#和MongoDB 3.0。我在多线程环境中插入了数百万个文档,但无法使MongoDB崩溃。
Parallel.For(0, 10000, (x =>
{
var lstDocs = new List<BsonDocument>();
for (var i = 0; i < 100; i++)
{
lstDocs.Add(new BsonDocument(doc));
}
collection.InsertMany(lstDocs);
lstDocs.Clear();
}));
你可以找到代码的要点here。
你自己试过这个吗?结果是什么?告诉我们你的努力。 – Saleem
@Saleem我已经添加了代码示例以及错误。 –
这可能是司机的问题。你正在使用哪个驱动程序版本?也请提及MongoDB版本。 – Saleem