我正在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_conconnect()时获得的值相同。
关闭与mysql_close(db_connection)的连接或执行查询都没有问题,因此db_connection(由db_connect()返回)是有效的。
如果我把db_connection作为全局变量,那么db_close()也可以,但我试图避免全局变量。
以上代码为简化版本。我尝试了一些方法,比如将MYSQL**作为db_connection传递,但我没有让它发挥作用。
信息和/或一些示例代码将是伟大的!
首先,一个简单但有点"不正确"的解决方案可能是只使用一个名为"db_action"的函数,该函数接收一个充当某种标志的整数变量:当标志为"0"时,您尝试连接到数据库,当标志为"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;
}
这是如果你真的想使用全局变量来创建一个void。在我看来,连接变量应该是全局的是有道理的,因为它可能会在程序的整个运行时间内使用,并由不同的函数使用。在许多针对c/php/ruby等的mysql基本教程中,它们通常使用全局变量。
我想让您理解为什么不能在db_close函数中将db_connection变量设置为NULL。
当您在db_connect函数中首次声明static MYSQL *db_connection = NULL;
时,您正在创建一个新的静态变量(这意味着它只初始化一次),并将其设置为NULL。你可以在这里阅读更多:维基百科静态变量
然后退出(代码退出…)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服务器请求,以避免在等待DB服务器回复时阻塞工作线程
第一个问题通过persistence.c G-WAN示例得到了解决。
第二个问题通过stream3.c示例解决。
stream4.c在另一个例子中合并了这两个解决方案,但它是为注册用户发布的最新稳定版本(v4.12.19)
希望能有所帮助。