[英]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 ++或类似语言有更大的责任来管理程序中不同变量的内存分配。 在这里阅读有关它的更多信息: 内存分配,堆和堆栈
汤姆。
您的脚本要考虑两个问题:
global
以发出多个请求并最终关闭连接; asynchonous
SQL服务器请求,以避免在等待数据库服务器答复时阻塞工作线程。 第一个问题由persistence.c G-WAN示例解决。
第二个问题由stream3.c示例解决。
stream4.c在另一个示例中合并了这两个解决方案,但是它随注册用户一起发布了最新的稳定版本(v4.12.19)。
希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.