缓存 sqlx 池会导致文件句柄溢出

问题描述

我计划有一个使用 sqlite 数据库作为数据文件的应用程序。 因为可以更频繁地打开不同的文件,所以我想缓存连接。

我对 Rust 很陌生;这是我的第一个项目... 我的问题是:有时当我用完文件句柄时,我无法创建新的数据库文件

到目前为止我尝试过的:

  • test1(),只有在我为 MyPool 实现 Drop 时才有效。 Drop 将关闭连接池。通过这样做,我确信文件句柄再次获得自由。
  • test2(),是我的项目需要的异步版本(它将是一个 Rocket 应用程序)。在这里,我一点也不成功。

如果您运行代码,则必须在之后删除所有 db.* 文件

// Cargo.toml
// tokio = { version = "1",features = ["rt-multi-thread","macros" ] }
// futures = "0.3"
// sqlx = { version = "0.5",features = [ "runtime-tokio-native-tls","sqlite","migrate" ] }

use sqlx::{migrate::MigrateDatabase,sqlite::sqlitePoolOptions,Pool,sqlite};
use futures::executor::block_on;
use std::sync::{Arc,Mutex};

#[derive(Clone)]
struct MyPool(Pool<sqlite>);

impl Drop for MyPool {
    fn drop(&mut self) {
        println!("**** drop");
        block_on(
            self.0.close()
        );
    }
}

#[tokio::main]
async fn main() {
    test1().await;
    //test2().await;
}

async fn test1() {
    let mut pool: Vec<MyPool> = Vec::new();

    for i in 1..1000 {

        let db_name = format!("./db.{}.db",i);

        sqlite::create_database(&db_name)
            .await.expect(format!("create {} Failed",i).as_str());

        let conn = sqlitePoolOptions::new()
            .max_connections(5)
            .connect(&db_name).await.expect(format!("connect {} Failed",i).as_str());

        if pool.len() == 10 {
            println!("Clenup");
            pool.clear();
        }

        println!("{}",i);
        pool.push(MyPool(conn));
    }
}

async fn test2() {
    let pool: Arc<Mutex<Vec<MyPool>>> = Arc::new(Mutex::new(Vec::new()));

    let tasks: Vec<_> = (0..1000)
    .map(|i| {
        let my_pool = pool.clone();

        tokio::spawn(async move {

            let db_name = format!("./db.{}.db",i);

            sqlite::create_database(&db_name)
                .await.expect(format!("create {} Failed",i).as_str());

            let conn = sqlitePoolOptions::new()
                .max_connections(5)
                .connect(&db_name).await.expect(format!("connect {} Failed",i).as_str());

            {
                let mut locked_pool = my_pool.lock().expect("locked");
                if locked_pool.len() == 10 {
                    println!("Clenup");
                    locked_pool.clear();
                }

                println!("{}",i);
                locked_pool.push(MyPool(conn));
            }

        })
    }).collect();

    // Wait for all tasks to complete.
    futures::future::join_all(tasks).await;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)