mongodb 中的并发写入

adn*_*ran 1 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();
            });
    });
}
Run Code Online (Sandbox Code Playgroud)

两个 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)
Run Code Online (Sandbox Code Playgroud)

当我检查输入数据库的条目数时,两个集合中已经输入了大约 4000 个条目。因此,我从上述实验中得到的是,当在其他集合中尝试写入时,可能会发生错误,而文档必须已被写入。

那么我应该如何继续实现这种并发而不发生锁冲突。

Nic*_*las 5

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

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