2016-03-06 151 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