网络编程对服务器的处理性能要求挺高,其中大多数服务器需要与数据库交互。
如果在服务器需要访问数据库才去建立短连接,会对服务器的性能大打折扣。
如果服务器的每个功能块都保有一个可用的长连接,对mysql数据库的连接数资源占用又偏大。
折中的办法就是在服务器启动时,建立一个数据库连接池,对池中的mysql数据库连接进行按需分配,实现资源的最优化利用。
数据库连接池构造如下:
1.在程序初始化时,建立一根单链表。(由于主要是读取操作)
2.单链表的节点中,含有一个互斥信号量,标志该连接是否已经被使用。pthread_mutex_trylock()函数提供了原子操作。
3.若连接可用,将互斥信号量锁住独占连接,即:从连接池中取出连接。
4.释放互斥锁,即:将连接释放入连接池
数据库连接池的数据结构如下:
-
#define DB_MAX_STRLNE 64
-
-
typedef struct _SQL_SOCK{
-
MYSQL * sock;
-
} SQL_SOCK;
-
-
typedef int (* IS_DB_CONN_FUNC)(void *);
-
typedef SQL_SOCK *(* DB_CONN_SINGLE_FUNC)(void *, void *, void *, void *, unsigned short);
-
typedef void (* DB_SOCK_DESTROY_FUNC)(void *);
-
-
typedef struct _SQL_SOCK_NODE{
-
struct _SQL_SOCK_NODE * next;
-
SQL_SOCK * sql_sock;
-
pthread_mutex_t sql_lock;
-
enum {DB_DISCONN, DB_CONN} sql_state;
-
} SQL_SOCK_NODE;
-
-
#include <pthread.h>
-
-
typedef struct _POOL_SQL_SOCK{
-
SQL_SOCK_NODE * sql_pool;
-
char db_host[DB_MAX_STRLNE];
-
char db_user[DB_MAX_STRLNE];
-
char db_passwd[DB_MAX_STRLNE];
-
char db_name[DB_MAX_STRLNE];
-
unsigned short db_port;
-
IS_DB_CONN_FUNC db_is_connect;
-
DB_CONN_SINGLE_FUNC db_conn_single;
-
DB_SOCK_DESTROY_FUNC db_sock_destroy;
-
} POOL_SQL_SOCK;
初始化数据库连接池:
-
static POOL_SQL_SOCK * sql_sock_pool = NULL;
-
-
int sql_pool_create(int c, char * db_host,
-
char * db_user, char * db_passwd,
-
char * db_name, unsigned short port,
-
IS_DB_CONN_FUNC is_conn,
-
DB_CONN_SINGLE_FUNC db_conn_single,
-
DB_SOCK_DESTROY_FUNC db_sock_close)
-
{
-
int i = 0;
-
SQL_SOCK_NODE * new_node;
-
-
//参数检查
-
if (!(db_host && db_user && db_passwd && db_name))
-
return 2;
-
-
sql_sock_pool = (POOL_SQL_SOCK *)malloc(sizeof(POOL_SQL_SOCK));
-
//内存分配不成功
-
if (NULL == sql_sock_pool)
-
return 1;
-
-
memset(sql_sock_pool, 0, sizeof(*sql_sock_pool));
-
sql_sock_pool->db_conn_single = db_conn_single;
-
sql_sock_pool->db_is_connect = is_conn;
-
sql_sock_pool->db_sock_destroy = db_sock_close;
-
strncpy(sql_sock_pool->db_host, db_host, DB_MAX_STRLNE);
-
strncpy(sql_sock_pool->db_user, db_host, DB_MAX_STRLNE);
-
strncpy(sql_sock_pool->db_passwd, db_host, DB_MAX_STRLNE);
-
strncpy(sql_sock_pool->db_name, db_host, DB_MAX_STRLNE);
-
-
for(; i < c; i ++) {
-
new_node = (SQL_SOCK_NODE *)malloc(sizeof(SQL_SOCK_NODE));
-
if (new_node)
-
goto POOL_CREATE_FAILED;
-
memset(new_node, 0, sizeof(*new_node));
-
-
if(pthread_mutex_init(&new_node->sql_lock)) {
-
free(new_node);
-
goto POOL_CREATE_FAILED;
-
}
-
new_node->sql_sock = db_conn_single(sql_sock_pool->db_host, sql_sock_pool->db_user
-
sql_sock_pool->db_passwd, sql_sock_pool->db_name);
-
if (NULL == new_node->sql_sock)
-
goto POOL_CREATE_FAILED;
-
new_node->sql_state = DB_CONN;
-
-
new_node->next = sql_sock_pool->sql_pool;
-
sql_sock_pool->sql_pool = new_node;
-
}
-
return 0;
-
POOL_CREATE_FAILED:
-
sql_pool_destroy();
-
return -1;
-
}
销毁连接池:
-
void sql_pool_destroy()
-
{
-
SQL_SOCK_NODE * tmp, *head = sql_sock_pool->sql_pool;
-
-
while(head) {
-
tmp = head;
-
head = head->next;
-
-
pthread_mutex_lock(&tmp->sql_lock);
-
sql_sock_pool->db_sock_destroy(tmp->sql_sock);
-
pthread_mutex_unlock(&tmp->sql_lock);
-
pthread_mutex_destroy(&tmp->sql_lock);
-
free(tmp);
-
}
-
}
从数据库连接池中取出连接:
-
SQL_SOCK_NODE * get_sock_from_pool()
-
{
-
static SQL_SOCK_NODE * last_used = sql_sock_pool->sql_pool;
-
SQL_SOCK_NODE * ret = NULL;
-
-
//防止出现问题
-
if (NULL == last_used)
-
return NULL;
-
-
ret = last_used->next;
-
-
while(ret != last_used) {
-
if (ret == NULL)
-
ret = sql_sock_pool->sql_pool;
-
-
if (0 == pthread_mutex_trylock(&ret->sql_lock)) {
-
//决定是否重新连接
-
if ((DB_DISCONN == ret->sql_state) &&
-
(!(ret->sql_sock) || (0 == sql_sock_pool->db_is_connect(ret->sql_sock)))) {
-
sql_sock_pool->db_sock_destroy(ret->sql_sock);
-
-
ret->sql_sock = sql_sock_pool->db_conn_single(sql_sock_pool->db_host,
-
sql_sock_pool->db_user, sql_sock_pool->db_passwd, sql_sock_pool->db_name);
-
-
//数据库不能建立连接,进程应该等待数据库恢复正常
-
if (NULL == ret->sql_sock) {
-
pthread_mutex_unlock(&ret->sql_lock);
-
return NULL;
-
}
-
-
}
-
-
last_used = ret;
-
return ret;
-
}
-
-
//获取当前连接不成功
-
ret = ret->next;
-
}
-
-
//连接池连接被耗尽
-
return NULL;
-
}
将连接放回数据库连接池:
-
void release_sock_to_sql_pool(SQL_SOCK_NODE * n)
-
{
-
pthread_mutex_unlock(&n->sql_lock);
-
}
使用数据库连接出现错误时,及时通知数据库调整的机制
-
void check_sql_sock_normal(SQL_SOCK_NODE * n)
-
{
-
n->sql_state = DB_DISCONN;
-
}
阅读(5188) | 评论(0) | 转发(0) |