LINUX C++ 数据库连接池
来源:互联网 发布:手机怎么进淘宝直通车 编辑:程序博客网 时间:2024/05/21 10:16
mysql的c++连接池 xPool
来自: http://my.oschina.net/u/1179554/blog/149560
最近待业,闲的蛋疼,发现C++下连mysql连接池这么基础的东西都没用过,身为一名计算机毕业生,深感愧疚,遂生一想法,写个或者找个连接池,以增强本人垃圾一样的专业修养。
没想到写出来第一版就存在内存管理问题导致的coredump,查了半天,发现是调用了空指针的成员函数,彻底晕倒,其间为了调试gdb core中bt出来的libmysqlclient.so的mysql_real_connect调用,我下了mysql的5.5.31源代码来编了若干遍,想编个debug版调试最后也是没有成功。发现问题还是看网上帖子讲segfault11这种问题多半都是空指针搞的,反过头加了些指针的打印语句才意识到低级的错误,后来debug过程中还发现了更低级的逻辑错误,略去不表,还是自己太菜,连个空指针这个白痴的内存问题都不预先防范,搞得一个300+行的东西,弄了三天才算稳定了,大大的罪过,浪费自己和社会的生产力。
过程中想到自己既然写不好,干脆找个好用的,结果发现了个libzdb,支持好些个开源db的连接池,随便下了个破代码测了一下,也没仔细搞,debug中参考了一下它的源码,还算是有点启发。
目前这个源码用valgrind自己测,有74KB左右的内存泄露,明白人能改改的话最好,作为一个菜鸟我只能帮自己到这了,当然这个泄露不会随时间线性的增长,这个我还是测过了的,有人能用到生产环境的话,麻烦给我提点改进意见,72小时的作品,太经不起考验了,目前本机上只能支持最多 152条连接,设成153就会报连接失败,牛逼的前辈们狠狠的批这份代码好了,自己也感觉自己水平太残废了,不知道是mysql设置还是系统设置的问题,总之无论是建议还是问题尽管扔过来吧,作为一个傻逼二货我照单全收。
上代码
去Github搞代码看这里 https://github.com/githcx/xPool
pool.h (1 in 3)
01
#include <mysql.h>
02
#include <stdio.h>
03
#include <string.h>
04
#include <map>
05
#include <vector>
06
#include <string>
07
#include <iostream>
08
#include <pthread.h>
09
10
using
std::string;
11
using
std::vector;
12
13
class
Connection;
14
15
class
some{
16
public
:
17
some(){}
18
Connection * first;
19
bool
second;
20
};
21
22
class
Pool{
23
public
:
24
static
int
initPool(string host,string user,string pass,string dbname,
int
poolSize);
25
static
void
destroyPool();
26
27
static
Connection* getConnection();
28
static
int
releaseConnection(Connection*);
29
static
void
lock();
30
static
void
unlock();
31
32
static
void
locke();
33
static
void
unlocke();
34
35
static
void
locki();
36
static
void
unlocki();
37
38
static
void
lockl();
39
static
void
unlockl();
40
41
42
private
:
43
44
static
pthread_mutex_t mutex;
45
static
pthread_mutex_t execmutex;
46
static
pthread_mutex_t initmutex;
47
static
pthread_mutex_t logmutex;
48
static
Pool* pool_;
49
50
private
:
51
some* vec;
// need an instance to init
52
53
public
:
54
static
string host_ ;
55
static
string user_ ;
56
static
string pass_ ;
57
static
string dbname_;
58
static
int
poolSize_ ;
59
60
public
:
61
62
Pool(string host,string user,string pass,string dbname,
int
poolSize);
63
virtual
~Pool();
64
};
65
66
class
QueryResult;
67
68
class
Connection{
69
public
:
70
Connection(string host,string user,string pass,string dbname);
71
virtual
~Connection();
72
73
QueryResult executeQuery(string statement);
74
private
:
75
// MYSQL代表了一条TCP连接
76
MYSQL* conn;
77
};
78
79
class
QueryResult{
80
public
:
81
int
getRowCount(){
return
string_table.size();}
82
int
getColumnCount(){
return
string_table[0].size();};
83
string getElement(
int
row,
int
column){
return
string_table[row][column];}
84
void
addRow(
const
vector<string>& row){string_table.push_back(row);}
85
private
:
86
vector<vector<string> > string_table;
87
};
pool.h (2 in 3)
001
#include "pool.h"
002
#include <stdlib.h>
003
004
// for DEBUG
005
using
std::cout;
006
using
std::endl;
007
008
009
// static field init
010
string Pool::host_ =
""
;
011
string Pool::user_ =
""
;
012
string Pool::pass_ =
""
;
013
string Pool::dbname_ =
""
;
014
int
Pool::poolSize_ = 0;
015
Pool* Pool::pool_ = NULL;
016
pthread_mutex_t Pool::mutex;
017
pthread_mutex_t Pool::execmutex;
018
pthread_mutex_t Pool::initmutex;
019
pthread_mutex_t Pool::logmutex;
020
021
void
Pool::lock(){
022
pthread_mutex_lock(&mutex);
023
}
024
025
void
Pool::unlock(){
026
pthread_mutex_unlock(&mutex);
027
}
028
029
void
Pool::locke(){
030
pthread_mutex_lock(&execmutex);
031
}
032
033
void
Pool::unlocke(){
034
pthread_mutex_unlock(&execmutex);
035
}
036
037
void
Pool::locki(){
038
pthread_mutex_lock(&initmutex);
039
}
040
041
void
Pool::unlocki(){
042
pthread_mutex_unlock(&initmutex);
043
}
044
045
void
Pool::lockl(){
046
pthread_mutex_lock(&logmutex);
047
}
048
049
void
Pool::unlockl(){
050
pthread_mutex_unlock(&logmutex);
051
}
052
053
054
055
Pool::Pool(string host,string user,string pass,string dbname,
int
poolSize){
056
057
vec =
new
some[Pool::poolSize_];
058
059
060
for
(
int
i=0; i<poolSize_; i++){
061
Connection* conn =
new
Connection(Pool::host_,Pool::user_,Pool::pass_,Pool::dbname_);
062
//std::cout << conn << std::endl;
063
//std::cout << host << " " << user << " " << pass << " " << dbname << " " << poolSize << std::endl;
064
if
(!conn){
065
cout <<
"xPool: new Connection Operation failed"
<< endl;
066
exit
(-1);
067
}
068
vec[i].first = conn;
069
vec[i].second =
false
;
070
}
071
072
073
}
074
075
Pool::~Pool(){
076
for
(
int
i=0;i<poolSize_;i++){
077
delete
vec[i].first;
078
}
079
delete
[] vec;
080
//mysql_library_end();
081
}
082
083
int
Pool::initPool(string host,string user,string pass,string dbname,
int
poolSize){
084
host_ = host;
085
user_ = user;
086
pass_ = pass;
087
dbname_ = dbname;
088
poolSize_ = poolSize;
089
090
return
0;
091
}
092
093
void
Pool::destroyPool(){
094
if
(pool_){
095
delete
pool_;
096
pool_ = NULL;
097
}
098
}
099
100
Connection* Pool::getConnection(){
101
102
// init pool, open connections
103
Pool::locki();
104
if
(pool_ == NULL){
105
pthread_mutex_init(&mutex,0);
106
pthread_mutex_init(&execmutex,0);
107
108
//mysql_library_init(0,NULL,NULL);
109
110
pool_ =
new
Pool(host_,user_,pass_,dbname_,poolSize_);
111
}
112
Pool::unlocki();
113
114
//get connection operation
115
Connection* ret = NULL;
116
while
(
true
){
117
Pool::lock();
118
bool
flag =
false
;
119
for
(
int
i=0;i<poolSize_;i++){
120
if
(pool_->vec[i].second ==
false
){
121
pool_->vec[i].second =
true
;
122
ret = pool_->vec[i].first;
123
flag =
true
;
124
break
;
125
}
126
}
127
if
(flag ==
true
){
128
Pool::unlock();
129
break
;
130
}
131
else
{
132
//cout << "wait" << endl;
133
Pool::unlock();
134
usleep(1000);
135
continue
;
136
}
137
}
138
return
ret;
139
}
140
141
int
Pool::releaseConnection(Connection* conn){
142
lock();
143
for
(
int
i=0;i<poolSize_;i++){
144
if
(pool_->vec[i].first == conn ){
145
pool_->vec[i].second =
false
;
146
break
;
147
}
148
}
149
unlock();
150
return
1;
151
}
152
153
154
Connection::Connection(string host,string user,string pass,string dbname){
155
156
static
int
connectionCount = 0;
157
158
//cout << "C#:" << connectionCount++ << endl;
159
160
// 初始化连接
161
conn = mysql_init(NULL);
162
163
//cout << "conn:" << conn << endl;
164
165
// 执行物理的tcp连接动作,完成三次握手
166
if
(!mysql_real_connect(conn,
"localhost"
,
"root"
,
"jiqim1ma"
,
"hcx"
,0,NULL,0)){
167
printf
(
"xPool: Error connecting to database: %s\n"
,mysql_error(conn));
168
exit
(-1);
169
}
170
else
{
171
}
172
}
173
174
Connection::~Connection(){
175
176
//mysql_thread_end();
177
178
// 关闭TCP连接,四次挥手
179
mysql_close(conn);
180
}
181
182
QueryResult Connection::executeQuery(string statement){
183
184
//Pool::locke();
185
186
//cout << "0.start query" << endl;
187
188
const
char
* query = statement.c_str();
189
190
//cout << "1.before mysql_real_query" << endl;
191
192
//cout << "strlen=[" << strlen(query) << "]" << endl;
193
194
unsigned
int
len = (unsigned
int
)
strlen
(query);
195
196
char
q[100];
197
strncpy
(q,query,len);
198
q[len]=0;
199
200
int
status = mysql_real_query(conn,q,len);
201
202
//cout << "1.after mysql_real_query" << endl;
203
204
if
(status){
205
printf
(
"Error making query: %s\n"
,
206
mysql_error(conn));
207
}
208
else
{
209
//printf("[%s] made...\n", query);
210
}
211
212
MYSQL_RES* resultSet;
213
214
//cout << "2.before mysql_store_result" << endl;
215
216
resultSet = mysql_store_result(conn);
217
218
//cout << "2.after mysql_store_result" << endl;
219
220
//cout << "3.before mysql_fetch_row" << endl;
221
222
QueryResult queryResult;
223
while
(
true
){
224
225
MYSQL_ROW row;
226
if
(!(row = mysql_fetch_row(resultSet))){
227
break
;
228
}
229
230
vector<string> string_row;
231
for
(
int
i=0; i < mysql_num_fields(resultSet); i++){
232
string_row.push_back(row[i]);
233
}
234
235
queryResult.addRow(string_row);
236
}
237
238
//cout << "3.after mysql_fetch_row" << endl;
239
240
//cout << "4.before mysql_free_result" << endl;
241
242
mysql_free_result(resultSet);
//free result after you get the result
243
244
//cout << "4.after mysql_free_result" << endl;
245
246
247
//cout << "0.finish query" << endl;
248
249
//Pool::unlocke();
250
251
return
queryResult;
252
}
mine.cpp ( 3 in 3 )
01
#include "pool.h"
02
#include <unistd.h>
03
#include <stdlib.h>
04
using
std::cout;
05
using
std::endl;
06
07
void
* handler(
void
* arg){
08
long
tid = (
long
)arg;
09
10
//cout << "tid =[" << tid << "]" << endl;
11
Connection* conn = Pool::getConnection();
12
13
if
(!conn){
14
cout <<
"getConnection NULL pointer"
<< endl;
15
exit
(-1);
16
}
17
18
//cout << "Connection.this:" << conn << endl;
19
20
const
char
* query;
21
query =
"select * from student;"
;
22
23
QueryResult queryResult = conn->executeQuery(query);
24
25
Pool::releaseConnection(conn);
26
27
//for(int i=0;i<queryResult.getRowCount();i++){
28
// for(int j=0;j<queryResult.getColumnCount();j++){
29
// cout << queryResult.getElement(i,j) << " ";
30
// }
31
// cout << endl;
32
//}
33
}
34
35
36
int
main(
int
argc,
char
* argv[]){
37
string host =
"localhost"
;
38
string user =
"root"
;
39
string pass =
"jiqim1ma"
;
40
string dbname =
"hcx"
;
41
int
poolSize = 152;
42
43
Pool::initPool(host,user,pass,dbname,poolSize);
44
45
///std::cin.get();
46
47
unsigned
int
count = -1;
48
if
(argc>1){
49
count =
atoi
(argv[1]);
50
}
51
52
for
(
int
i=0;i < count;i++){
53
54
const
int
THREAD_COUNT = 250;
55
pthread_t threads[THREAD_COUNT];
56
for
(
long
i=0;i<THREAD_COUNT;i++){
57
pthread_create(&threads[i],NULL,handler,(
void
*)i);
58
//sleep(1);
59
}
60
61
for
(
int
i=0;i<THREAD_COUNT;i++){
62
pthread_join(threads[i],0);
63
}
64
65
cout <<
"==============================LOOPBACK================================="
<< endl;
66
}
67
68
Pool::destroyPool();
69
70
71
72
return
0;
73
}
Makefile
1
all: sbpool
2
3
sbpool: mine.cpp pool.cpp
4
g++ -g -o sbpool mine.cpp pool.cpp -lmysqlclient -lpthread
5
6
clean:
7
rm
-f *.o accessdb sbpool core*
mypool数据库连接池
来自:- LINUX C++ 数据库连接池
- 用C#建立数据库连接池
- C语言数据库连接池libzdb
- C#数据库连接
- Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)
- Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)
- Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)
- Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)
- C实现PHP的mysql数据库连接池
- C语言与数据库连接
- C#----判断数据库连接状态
- c#sqlserver数据库连接字符串
- 数据库连接(C++)
- linux occi 数据库连接
- 基于Mysql Connector(C++)的数据库连接池的实现
- libzdb c语言的数据库连接池支持库 源码分析
- 基于Mysql Connector(C++)的数据库连接池的实现
- 基于Mysql Connector(C++)的数据库连接池的实现
- c++ 虚函数的实现机制
- 《Java NIO》读书笔记
- 一个冒泡排序
- android 浏览器插件开发 - 流程(1)
- Lucene.net实现搜索
- LINUX C++ 数据库连接池
- Android开发者将越来越有前途
- 采用java链接timesten内存数据库
- android 浏览器插件开发 - HelloPlugin
- 热门同性恋社交网站 看下他们是怎么运营的。
- 深入学习java的HashMap实现原理
- OCP-1Z0-051 补充题库 第6题 SELECT查询语句
- Qt之实现好友列表
- 【Python】decorator的作用