繁体   English   中英

在C函数中将MySQL连接保持在函数的静态变量中(避免全局变量)

[英]Keep MySQL connection in static variable in function (avoid global variables) in C

我正在C中创建一个MySQL层(将在GWAN中运行),并试图避免将MySQL连接保留在全局变量中。

我的简化代码如下所示:

    #include <mysql.h>

    const char *DB_HOST = "localhost";
    const char *DB_USER = "user";
    const char *DB_PASSWORD = "pass";
    const char *DB_DATABASE = "xxx";
    const unsigned int DB_PORT = 3306;
    const char *DB_CHARACTER_SET = "utf8";
    const char *DB_SOCKET = 0;
    const unsigned long DB_CLIENT_FLAG=0;

    typedef struct DB_Data {
        //database returned data
    } DB_Data;

    //connect to database and return the connection
    MYSQL *db_connect() {

        static MYSQL *db_connection = NULL;

        if(db_connection == NULL) {

            printf(" NEW CONN \n");

            db_connection = (MYSQL *)mysql_init(NULL);

            if(!db_connection) {
                return NULL;
            }

            //connect to the database using settings
            if(mysql_real_connect(db_connection, DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE, DB_PORT, DB_SOCKET, DB_CLIENT_FLAG) == NULL) {
                return NULL;
            }

            //set character set
            if (mysql_set_character_set(db_connection, DB_CHARACTER_SET)) {
                return NULL;
            }

        }else{
            printf(" OLD CONN \n");
        }

        return db_connection;
    }

    //close the database connection
    void db_close() {

        //get connection
        MYSQL *db_connection = db_connect();

        if(db_connection != NULL) {

            printf("\n closing... \n");

            //close connection
            mysql_close(db_connection);

            //set pointer to null
            //Fail: this does not effect the static variable in db_connect()
            db_connection = NULL;
        }
    }

    //query the database
    DB_Data *db_query(char *sql, bool getResult) {

        DB_Data *rtn;
        MYSQL_ROW row = NULL;

        //create connection if not already done
        MYSQL *db_connection = db_connect();
        //db_connect();
        if(db_connection == NULL) {
            return NULL;
        }

        if(mysql_query(db_connection, sql) != 0) {
            return NULL;
        }

        if(getResult != true) {
            return NULL;
        }

        MYSQL_RES *result = mysql_store_result(db_connection);

      if(result == NULL) {
            return NULL;
      }

        while ((row = mysql_fetch_row(result))) {
            //process data
            printf("Process data \n");
        }

        mysql_free_result(result);

        return rtn;
    }

一切正常,直到我开始使用db_close()关闭连接。 在我的代码中似乎失败的是,在db_close()中db_connection没有设置为NULL。 在运行db_close()并再次运行db_connect()之后,db_connection的值不为NULL,但与第一次运行db_connect()时获得的值相同。

使用mysql_close(db_connection)关闭连接或执行查询没有问题,因此db_connection(由db_connect()返回)有​​效。

如果我将db_connection用作全局变量,则db_close()也可以工作,但是我试图避免使用全局变量。

上面的代码是简化版本。 我已经尝试了一些方法,例如将MYSQL **传递为db_connection,但是我没有使它起作用。

信息和/或一些示例代码会很棒!

首先-一个简单但有点“歪”的解决方案可能是只使用一个名为“ db_action”的函数,该函数接收充当一种标志的整数变量:当标志为“ 0”时,您尝试连接到DB,并且当标志为“ 1”时,您将其断开连接:

    MYSQL *db_action(int flag) {

    static MYSQL *db_connection = NULL;

    if(flag == 0 && db_connection == NULL) {

        printf(" NEW CONN \n");

        db_connection = (MYSQL *)mysql_init(NULL);

         ...
    }
    else if(flag == 1 && db_connection != NULL){
        printf("\n closing... \n");

        //close connection
        mysql_close(db_connection);

        //set pointer to null
        db_connection = NULL;
    }
    else{           
        printf(" OLD CONN \n");
    }

    return db_connection;
}

这是如果您真的想使用全局变量来作废。 在我看来,您的连接变量应该是全局的,这是有道理的,因为它可能会在程序的整个运行时使用,并由不同的功能使用。 在许多针对c / php / ruby​​等的基本mysql教程中,它们通常使用全局变量。

我想让您理解为什么不能在db_close函数中将db_connection变量设置为NULL。

当您首先声明static MYSQL *db_connection = NULL; 在db_connect函数中,您正在创建一个新的静态变量(这意味着它仅被初始化一次)并将其设置为NULL。 您可以在此处阅读更多内容: Wikipedia static_variable

然后退出(您的代码退出...)db_connect函数。 现在,db_connection变量已超出范围-您无法“使用”它(读取或更改它的数据)。 您只能在db_connect函数中执行此操作。

在db_close中,您将获得先前的数据库连接, MYSQL *db_connection = db_connect(); 但是请注意,因为您已声明* db_connection为MYSQL类型的新变量(它是MYSQL变量的指针),所以它现在处于db_close函数的范围内-它不能影响您先前创建的静态变量-它们是两个不同的变量-当您调用db_connect()时,它们仅共享相同的数据。

在开发任何类型的软件时,都必须了解范围和/或堆/堆栈机制。 尤其是当您作为程序员时,C / C ++或类似语言有更大的责任来管理程序中不同变量的内存分配。 在这里阅读有关它的更多信息: 内存分配,堆和堆栈

汤姆。

您的脚本要考虑两个问题:

  • 您需要使MySQL套接字保持global以发出多个请求并最终关闭连接;
  • 您需要发出一个asynchonous SQL服务器请求,以避免在等待数据库服务器答复时阻塞工作线程。

第一个问题由persistence.c G-WAN示例解决。

第二个问题由stream3.c示例解决。

stream4.c在另一个示例中合并了这两个解决方案,但是它随注册用户一起发布了最新的稳定版本(v4.12.19)。

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM