当我在集合中插入/更新文档时,是否在数据库或集合上应用了锁。假设我有两个集合,它们在同一个数据库中彼此独立,并且希望同时对它们进行写操作。这可能吗?
以下是我用来测试此代码的代码:
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个条目。所以我从上面的实验得到的结果是,当一个写入被尝试时,可能发生了一个错误,而在其他集合中,文档必须已经被写入。
那么我应该如何在没有冲突的情况下继续保持这种并发性。
答案 0 :(得分:2)
这个问题的答案可能很长,取决于各种因素(MongoDB版本,存储引擎,您正在进行的操作类型,分片等)。我只建议您仔细阅读MongoDB文档的Concurrency部分,特别是lock granularity part。
请确保首先选择正确版本的MongoDB,因为从一个版本到另一个版本的行为差异很大(例如3.0版本中的数据库锁定与3.0版后使用NMAPv1的大多数操作的集合锁定)。
答案 1 :(得分:0)
我不认为它与MongoDB的并发问题,但我可能是驱动程序,甚至可能是测试本身。 我几周前创建了一个示例应用程序,以便在处理一个讨厌的bug时对MongoDB进行压力测试。我在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();
}));
您可以在gist here中找到代码。
答案 2 :(得分:0)
您不应该每次都调用MongoClient.connect。这导致大量的连接始终打开和关闭,这导致mongo过载。您应该让MongoClient管理连接池。对其进行更改,以便从MongoClient.connect存储db对象。像这样:
var db
MongoClient.connect(url, function(err, database){
db = database;
}