Chinaunix首页 | 论坛 | 博客
  • 博客访问: 102981
  • 博文数量: 24
  • 博客积分: 105
  • 博客等级: 民兵
  • 技术积分: 244
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-09 20:05
文章分类

全部博文(24)

文章存档

2015年(1)

2014年(9)

2013年(10)

2012年(4)

我的朋友

分类: LINUX

2013-05-03 21:51:38

网络编程对服务器的处理性能要求挺高,其中大多数服务器需要与数据库交互。
如果在服务器需要访问数据库才去建立短连接,会对服务器的性能大打折扣。
如果服务器的每个功能块都保有一个可用的长连接,对mysql数据库的连接数资源占用又偏大。
折中的办法就是在服务器启动时,建立一个数据库连接池,对池中的mysql数据库连接进行按需分配,实现资源的最优化利用。


数据库连接池构造如下:
1.在程序初始化时,建立一根单链表。(由于主要是读取操作)
2.单链表的节点中,含有一个互斥信号量,标志该连接是否已经被使用。pthread_mutex_trylock()函数提供了原子操作。
3.若连接可用,将互斥信号量锁住独占连接,即:从连接池中取出连接。
4.释放互斥锁,即:将连接释放入连接池

数据库连接池的数据结构如下:

点击(此处)折叠或打开

  1. #define DB_MAX_STRLNE    64

  2. typedef struct _SQL_SOCK{
  3.     MYSQL * sock;
  4. } SQL_SOCK;

  5. typedef int (* IS_DB_CONN_FUNC)(void *);
  6. typedef SQL_SOCK *(* DB_CONN_SINGLE_FUNC)(void *, void *, void *, void *, unsigned short);
  7. typedef void (* DB_SOCK_DESTROY_FUNC)(void *);

  8. typedef struct _SQL_SOCK_NODE{
  9.     struct _SQL_SOCK_NODE * next;
  10.     SQL_SOCK * sql_sock;
  11.     pthread_mutex_t sql_lock;
  12.     enum {DB_DISCONN, DB_CONN} sql_state;
  13. } SQL_SOCK_NODE;

  14. #include <pthread.h>

  15. typedef struct _POOL_SQL_SOCK{
  16.     SQL_SOCK_NODE * sql_pool;
  17.     char db_host[DB_MAX_STRLNE];
  18.     char db_user[DB_MAX_STRLNE];
  19.     char db_passwd[DB_MAX_STRLNE];
  20.     char db_name[DB_MAX_STRLNE];
  21.     unsigned short db_port;
  22.     IS_DB_CONN_FUNC db_is_connect;
  23.     DB_CONN_SINGLE_FUNC db_conn_single;
  24.     DB_SOCK_DESTROY_FUNC db_sock_destroy;
  25. } POOL_SQL_SOCK;



初始化数据库连接池:

点击(此处)折叠或打开

  1. static POOL_SQL_SOCK * sql_sock_pool = NULL;

  2. int sql_pool_create(int c, char * db_host,
  3.                 char * db_user, char * db_passwd,
  4.                 char * db_name, unsigned short port,
  5.                 IS_DB_CONN_FUNC is_conn,
  6.                 DB_CONN_SINGLE_FUNC db_conn_single,
  7.                 DB_SOCK_DESTROY_FUNC db_sock_close)
  8. {
  9.     int i = 0;
  10.     SQL_SOCK_NODE * new_node;

  11.     //参数检查
  12.     if (!(db_host && db_user && db_passwd && db_name))
  13.         return 2;
  14.     
  15.     sql_sock_pool = (POOL_SQL_SOCK *)malloc(sizeof(POOL_SQL_SOCK));
  16.     //内存分配不成功
  17.     if (NULL == sql_sock_pool)
  18.         return 1;

  19.     memset(sql_sock_pool, 0, sizeof(*sql_sock_pool));
  20.     sql_sock_pool->db_conn_single = db_conn_single;
  21.     sql_sock_pool->db_is_connect = is_conn;
  22.     sql_sock_pool->db_sock_destroy = db_sock_close;
  23.     strncpy(sql_sock_pool->db_host, db_host, DB_MAX_STRLNE);
  24.     strncpy(sql_sock_pool->db_user, db_host, DB_MAX_STRLNE);
  25.     strncpy(sql_sock_pool->db_passwd, db_host, DB_MAX_STRLNE);
  26.     strncpy(sql_sock_pool->db_name, db_host, DB_MAX_STRLNE);

  27.     for(; i < c; i ++) {
  28.         new_node = (SQL_SOCK_NODE *)malloc(sizeof(SQL_SOCK_NODE));
  29.         if (new_node)
  30.             goto POOL_CREATE_FAILED;
  31.         memset(new_node, 0, sizeof(*new_node));
  32.         
  33.         if(pthread_mutex_init(&new_node->sql_lock)) {
  34.             free(new_node);
  35.             goto POOL_CREATE_FAILED;
  36.         }
  37.         new_node->sql_sock = db_conn_single(sql_sock_pool->db_host, sql_sock_pool->db_user
  38.             sql_sock_pool->db_passwd, sql_sock_pool->db_name);
  39.         if (NULL == new_node->sql_sock)
  40.             goto POOL_CREATE_FAILED;
  41.         new_node->sql_state = DB_CONN;

  42.         new_node->next = sql_sock_pool->sql_pool;
  43.         sql_sock_pool->sql_pool = new_node;
  44.     }
  45.     return 0;
  46. POOL_CREATE_FAILED:
  47.     sql_pool_destroy();
  48.     return -1;
  49. }

销毁连接池:

点击(此处)折叠或打开

  1. void sql_pool_destroy()
  2. {
  3.     SQL_SOCK_NODE * tmp, *head = sql_sock_pool->sql_pool;

  4.     while(head) {
  5.         tmp = head;
  6.         head = head->next;

  7.         pthread_mutex_lock(&tmp->sql_lock);
  8.         sql_sock_pool->db_sock_destroy(tmp->sql_sock);
  9.         pthread_mutex_unlock(&tmp->sql_lock);
  10.         pthread_mutex_destroy(&tmp->sql_lock);
  11.         free(tmp);
  12.     }
  13. }

 
从数据库连接池中取出连接:

点击(此处)折叠或打开

  1. SQL_SOCK_NODE * get_sock_from_pool()
  2. {
  3.     static SQL_SOCK_NODE * last_used = sql_sock_pool->sql_pool;
  4.     SQL_SOCK_NODE * ret = NULL;

  5.     //防止出现问题
  6.     if (NULL == last_used)
  7.         return NULL;
  8.     
  9.     ret = last_used->next;
  10.     
  11.     while(ret != last_used) {
  12.         if (ret == NULL)
  13.             ret = sql_sock_pool->sql_pool;
  14.         
  15.         if (0 == pthread_mutex_trylock(&ret->sql_lock)) {
  16.             //决定是否重新连接
  17.             if ((DB_DISCONN == ret->sql_state) &&
  18.                 (!(ret->sql_sock) || (0 == sql_sock_pool->db_is_connect(ret->sql_sock)))) {
  19.                 sql_sock_pool->db_sock_destroy(ret->sql_sock);
  20.                 
  21.                 ret->sql_sock = sql_sock_pool->db_conn_single(sql_sock_pool->db_host,
  22.                     sql_sock_pool->db_user, sql_sock_pool->db_passwd, sql_sock_pool->db_name);

  23.                 //数据库不能建立连接,进程应该等待数据库恢复正常
  24.                 if (NULL == ret->sql_sock) {
  25.                     pthread_mutex_unlock(&ret->sql_lock);
  26.                     return NULL;
  27.                 }
  28.                 
  29.             }

  30.             last_used = ret;
  31.             return ret;
  32.         }

  33.         //获取当前连接不成功
  34.         ret = ret->next;
  35.     }

  36.     //连接池连接被耗尽
  37.     return NULL;
  38. }
将连接放回数据库连接池:

点击(此处)折叠或打开

  1. void release_sock_to_sql_pool(SQL_SOCK_NODE * n)
  2. {
  3.     pthread_mutex_unlock(&n->sql_lock);
  4. }

使用数据库连接出现错误时,及时通知数据库调整的机制

点击(此处)折叠或打开

  1. void check_sql_sock_normal(SQL_SOCK_NODE * n)
  2. {
  3.     n->sql_state = DB_DISCONN;
  4. }



阅读(4996) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~