Nodejs中mongodb的open和close疑问

Nodejs中mongodb的open和close疑问

在操作mongodb的时候经常遇到

Error: db object already connecting, open cannot be called multiple times

这种问题。 个人找到了原因,是因为上一次 mongodb.open(), 还没有来得及 mongodb.close() 就开始了下一次 mongodb.open()

我的疑问是这样的问题一般怎么处理,看到有人说打开一次就不关闭了,一直保持开始状态, 有人又说一直打开不好。

求教~


11 回复

Nodejs中mongodb的open和close疑问

在使用Node.js操作MongoDB时,经常会遇到如下错误:

Error: db object already connecting, open cannot be called multiple times

这个问题通常发生在你试图在数据库连接还未完全关闭的情况下再次打开数据库连接。具体来说,当你调用 mongodb.open() 方法时,如果前一次的 mongodb.open() 操作还未完成或 mongodb.close() 没有被正确调用,就会出现上述错误。

如何处理这种情况?

处理这种情况通常有两种方法:

  1. 确保每次操作后正确关闭数据库连接: 在每次数据库操作完成后,确保调用 mongodb.close() 来关闭连接。这样可以避免多次调用 mongodb.open() 导致的错误。

  2. 使用连接池管理连接: 使用连接池可以更高效地管理数据库连接,而不是每次都打开和关闭连接。MongoDB驱动程序提供了连接池功能,可以在应用启动时初始化一个连接池,并在整个应用生命周期内重用这些连接。

示例代码

以下是一个使用连接池的示例代码:

const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017';
const dbName = 'myproject';

// 创建一个连接池
let db;

MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log("Connected successfully to server");
    db = client.db(dbName);
});

async function insertDocument() {
    const collection = db.collection('documents');
    await collection.insertOne({ a: 1 });
    console.log("Document inserted successfully");
}

async function queryDocuments() {
    const collection = db.collection('documents');
    const docs = await collection.find().toArray();
    console.log(docs);
}

// 使用连接池进行操作
insertDocument().then(queryDocuments).catch(console.error);

在这个示例中,我们创建了一个全局变量 db 来存储数据库连接对象。在应用启动时,我们通过 MongoClient.connect 方法初始化连接池。之后的所有数据库操作都可以直接使用这个连接对象,而不需要重复打开和关闭连接。

总结

虽然保持数据库连接一直打开可能会导致资源浪费,但在某些场景下(如高并发环境),使用连接池可以提高性能和响应速度。因此,建议根据实际应用场景选择合适的方案。


先打开数据库,取得要获取的数据,然后再关闭数据库,我觉得这种用法应该比较多一些

我开始时这样用的,但是例如我两个ajax请求同事需要访问数据库,会导致一个数据库打开了还没有关闭,另外一个mongodb.open()出错

话说,node 是单线程的…你打开了…如果要一直跑的…也没必要关闭啊…

除非你是不需要一直运行的.才需要关闭 -打开

记住node 是单线程的…以前你用别的语言,说打开了,不关闭会导致内存泄露…但是,在node不存在这种情况…

哦,谢谢啦~~我后来就是改为一直打开不关闭了,这样就没有出现问题啦,之前就是担心如果老打开会不会导致问题~习惯性的每次用完就关闭~

打开就不要关了 因为有pool机制 底层会自己帮你处理

mongoDB连接本质就是TCP连接,只要创建新的TCP去连接mongo就可以了,不过需要记住关闭不用的连接。

这个我也遇到过,后来简单的看了一下mongodb的node驱动,发现一种简单的解决办法:

var mongodb = require('./db');

if(!mongodb.openCalled) mongodb.open(function(err, db){…}); else mongodb.collection(‘xxx’, function(err, collection){…});

这里有一个openCalled属性,可以用它来检测数据库是否已經被打开。 如果已经打开,则直接使用,否则再open

一种方法是直接从头open到尾。我也不推荐。

另一种就是用mongoose

进程启动,connect 以后,不要关闭,直接用就可以了。不要每个请求都 connect(), close()

在Node.js中使用MongoDB时,db.open()db.close() 的正确使用方式非常重要,以避免出现重复连接的问题。错误信息 Error: db object already connecting, open cannot be called multiple times 表明你尝试多次打开同一个数据库连接对象。

解决方法

  1. 确保每次操作后关闭连接: 如果你的应用对数据库的操作比较频繁且短暂,可以确保每次操作完成后调用 db.close() 来关闭连接。但要注意,在实际生产环境中频繁地打开和关闭连接可能会增加额外的开销。

  2. 保持连接: 对于长时间运行的应用(如Web服务器),保持数据库连接通常是个更好的选择。这样可以减少连接和断开连接的开销,提高性能。可以利用全局变量或者模块导出的方式保持一个持久化的数据库连接。

示例代码

方式一:每次操作后关闭连接

const MongoClient = require('mongodb').MongoClient;

function connectAndQuery(callback) {
    MongoClient.connect('mongodb://localhost:27017/myproject', { useNewUrlParser: true, useUnifiedTopology: true }, (err, db) => {
        if (err) return callback(err);
        const dbo = db.db("myproject");
        dbo.collection("users").find({}).toArray((err, result) => {
            db.close(); // 关闭连接
            if (err) return callback(err);
            callback(null, result);
        });
    });
}

connectAndQuery((err, result) => {
    if (err) throw err;
    console.log(result);
});

方式二:保持单个持久化连接

let db;

MongoClient.connect('mongodb://localhost:27017/myproject', { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => {
    if (err) throw err;
    db = client.db("myproject");
});

function queryDatabase() {
    db.collection("users").find({}).toArray((err, result) => {
        if (err) throw err;
        console.log(result);
    });
}

// 在需要的地方调用queryDatabase
queryDatabase();

这种方式通过全局变量 db 存储数据库连接对象,可以在多个函数或异步操作之间共享该连接,从而避免频繁的连接和断开操作。

回到顶部