在mongodb中同时写入

时间:2016-03-06 10:53:28

标签: 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个条目。所以我从上面的实验得到的结果是,当一个写入被尝试时,可能发生了一个错误,而在其他集合中,文档必须已经被写入。

那么我应该如何在没有冲突的情况下继续保持这种并发性。

3 个答案:

答案 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;
}