2016-03-06 96 views
-2

当我在集合中插入/更新文档时,锁是应用于数据库还是集合。假设我有两个集合,并且它们在同一个数据库中彼此独立,并且想要同时对它们执行写操作。这可能吗?在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项已经在这两个集合输入。所以我从上面的实验中得到的结果是,当一次写入正在尝试时,可能发生了错误,而在其他收集中,文档必须已经被写入。

那么我应该如何继续进行这种并发性而没有冲突的锁。

+0

你自己试过这个吗?结果是什么?告诉我们你的努力。 – Saleem

+0

@Saleem我已经添加了代码示例以及错误。 –

+0

这可能是司机的问题。你正在使用哪个驱动程序版本?也请提及MongoDB版本。 – Saleem

回答

1

这个问题的答案可能很长,取决于各种因素(MongoDB版本,存储引擎,正在进行的操作类型,分片等)。我只能建议您仔细阅读MongoDB文档的Concurrency部分,特别是lock granularity part

确保首先选择正确版本的MongoDB,因为每个版本的行为差别很大(例如3.0版之前的数据库锁定与3.0版之后的使用NMAPv1的大多数操作的集合锁定)。

0

我不认为这是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