先贴测试代码吧:/****************************** 测试代码 *******************************/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#include "mysql.h"#define NCONNECTS       1
#define NTHREADS        2
#define NTHREAD_INSERTS 5000#define BUFFSIZE        1024
#define DB_NAME_MAX     128
#define TABLE_NAME_MAX  70
#define DB_ERROR(my_conn, msg) db_show_error(__FILE__, __LINE__, my_conn, msg)/* 用于存储可用的mysql的空闲连接 */
struct mysql_conn_t
{
MYSQL my_conn;
int is_idle;
pthread_mutex_t mutex;
};/* 文件权限管理表,基于用户下载权限管理的表 */
struct FileStoreInfor_t
{
char FileServerMark[2+1];
char CryptVersion[16+1];
char UploadTime[32+1];
char FileCheckCode[32+1];
char FileUploadUser[32+1];
char FileUploadIp[32+1];
char FileClientMac[32+1];
char ChName[32+1];
char AppServerName[32+1];
char SourceFileName[32+1];
char FileStoreFullPath[64+1];
int  CryptMask;
int  FileLength;
int  FileCurrentLen;
int  FileState;
int  DownloadPriSeq;
int  FileDownloadPri;
};time_t g_time_start, g_time_end;
int g_nthread_ends, g_nmysql_inserts;
int  g_db_port;                         /* 数据库端口   */
char g_db_host[DB_NAME_MAX];            /* 数据库IP     */
char g_db_user[DB_NAME_MAX];            /* 数据库用户名 */
char g_db_passwd[DB_NAME_MAX];          /* 数据库密码   */
char g_db_dbname[DB_NAME_MAX];          /* 数据库名     */
struct mysql_conn_t g_conn[NCONNECTS];  /* 数据库连接   */void *count_thread(void *arg);
void db_show_error(const char *filename, int err_line, MYSQL *my_conn, const char *msg);
int db_init(const char *db_host, const char *db_user, const char *db_passwd, const char *db_dbname, int db_port);
int db_thread_init();
void db_thread_end();
int insert_storeinfo(const struct FileStoreInfor_t *storeinfo_ptr);
int db_connect();
int db_query(const char *query_cmd, MYSQL_RES **res_pptr);
void *storeinfo_insert_thread(void *arg);int main()
{
int nloops;
pthread_t id_storeinfo_insert, id_count; if(0 != pthread_create(&id_count, NULL, count_thread, NULL))
return 0; /* 主线程中必须调用db_init函数进行对数据库的初始化 */
/*          ip,  用户名,  密码, 数据库名, 数据库端口 */
if(0 != db_init(NULL, "root", "root",  "ufs",     0))
return 0;
/* 对FileStoreInfor和FileOperSeq表做nloops次插入 */
time(&g_time_start);
for(nloops=0; nloops<NTHREADS; nloops++) {
if(0 != pthread_create(&id_storeinfo_insert, NULL, storeinfo_insert_thread, NULL)) {
perror("pthread_create");
return 0;
}
} const useconds_t usec = 100;
while(NTHREADS > g_nthread_ends)
usleep(usec);
time(&g_time_end);
printf("\ntotal time(sec): %lu\n", g_time_end-g_time_start);
return 0;
}void *count_thread(void *arg)
{
const useconds_t usec = 1000; while(NTHREADS > g_nthread_ends) {
printf("\r%d/%d              ", g_nmysql_inserts, NTHREADS * NTHREAD_INSERTS);
fflush(stdout);
usleep(usec);
}
return NULL;
}/*
 * 函数说明: 显示错误原因(定义了MYSQL_DEBUG宏才显示)
 * 参数    : filename: 出错函数所在的源文件名
 *           err_line: 出错函数所在行数
 *           my_conn : mysql的一个连接(如果为NULL, 则不显示mysql提供的错误信息)
 *           msg     : 错误原因的标题
 * 返回值  : 无
 */
void db_show_error(const char *filename, int err_line, MYSQL *my_conn, const char *msg)
{
#ifdef MYSQL_DEBUG
if(NULL == msg)
msg = "";
printf("(%s %d) %s: (%d)%s\n", filename, err_line, msg
, mysql_errno(my_conn), mysql_error(my_conn));
#endif
}/*
 * 函数说明: 初始化数据库
 * 参数    : db_host  : 数据库的ip
 *           db_user  : 连接数据库的用户名
 *           db_passwd: 连接数据库的密码
 *           db_dbname: 数据库名
 *           db_port :  数据库使用的端口
 * 返回值  : 0成功, -1失败
 */
int db_init(const char *db_host, const char *db_user, const char *db_passwd, const char *db_dbname, int db_port)
{
char value;
int index; /* 将所传参数全都保存到全局变量中, 供后面使用 */
strncpy(g_db_host,   (db_host   ? db_host   : ""), sizeof(g_db_host));
strncpy(g_db_user,   (db_user   ? db_user   : ""), sizeof(g_db_user));
strncpy(g_db_passwd, (db_passwd ? db_passwd : ""), sizeof(g_db_passwd));
strncpy(g_db_dbname, (db_dbname ? db_dbname : ""), sizeof(g_db_dbname));
g_db_port = db_port; if(0 != mysql_library_init(0, NULL, NULL)) {
DB_ERROR(NULL, "mysql_library_init");
return -1;
}
value = 1;
for(index=0; index<NCONNECTS; index++) { /* 先创建个空闲的mysql连接池 */
if(NULL == mysql_init(&g_conn[index].my_conn)) {
DB_ERROR(NULL, "mysql_init");
return -1;
}
if(0 != mysql_options(&g_conn[index].my_conn, MYSQL_OPT_RECONNECT, &value)) { /* 启用自动重连 */
DB_ERROR(NULL, "mysql_options");
return -1;
}
if(NULL == mysql_real_connect(&g_conn[index].my_conn,
db_host, db_user, db_passwd, db_dbname, db_port, NULL, 0)) {
DB_ERROR(&g_conn[index].my_conn, "mysql_real_connect");
return -1;
}
if(0 != mysql_autocommit(&g_conn[index].my_conn, 1)) { /* 启用自动提交 */
DB_ERROR(NULL, "mysql_autocommit");
return -1;
}
g_conn[index].is_idle = 1; /*设为空闲连接 */
if(0 != pthread_mutex_init(&g_conn[index].mutex, NULL))
return -1;
}
return 0;
}/*
 * 函数说明: 初始化与线程相关的变量
 * 参数    : 无
 * 返回值  : 成功返回0, 失败返回-1
 */
int db_thread_init()
{
if(0 != mysql_thread_init()) {
DB_ERROR(NULL, "mysql_thread_init");
return -1;
}
return 0;
}/*
 * 函数说明: 释放为mysql数据库操作分配的内存
 * 参数    : 无
 * 返回值  : 无
 */
void db_thread_end()
{
mysql_thread_end();
}/*
 * 函数说明: 将FileStoreInfor结构体插入数据库的FileStoreInfor表
 * 参数    : storeinfo_ptr: 要插入的FileStoreInfor_t结构体的地址
 * 返回值  : 0成功,-1出错
 */
int insert_storeinfo(const struct FileStoreInfor_t *storeinfo_ptr)
{
char *col_name;
char insert_cmd[BUFFSIZE]; col_name = "FileServerMark,"
   "CryptVersion,"
   "UploadTime,"
   "FileCheckCode,"
   "FileUploadUser,"
   "FileUploadIp,"
   "FileClientMac,"
   "ChName,"
   "AppServerName,"
   "SourceFileName,"
   "FileStoreFullPath,"
   "CryptMask,"
   "FileLength,"
   "FileCurrentLen,"
   "FileState,"
   "DownloadPriSeq,"
   "FileDownloadPri"; snprintf(insert_cmd, sizeof(insert_cmd), "INSERT INTO FileStoreInfor(%s) "
"VALUES(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', "
"\'%s\', \'%s\', \'%s\', \'%s\', %d, %d, %d, %d, %d, %d)",
col_name,
storeinfo_ptr->FileServerMark,
storeinfo_ptr->CryptVersion,
storeinfo_ptr->UploadTime,
storeinfo_ptr->FileCheckCode,
storeinfo_ptr->FileUploadUser,
storeinfo_ptr->FileUploadIp,
storeinfo_ptr->FileClientMac,
storeinfo_ptr->ChName,
storeinfo_ptr->AppServerName,
storeinfo_ptr->SourceFileName,
storeinfo_ptr->FileStoreFullPath,
storeinfo_ptr->CryptMask,
storeinfo_ptr->FileLength,
storeinfo_ptr->FileCurrentLen,
storeinfo_ptr->FileState,
storeinfo_ptr->DownloadPriSeq,
storeinfo_ptr->FileDownloadPri);
return db_query(insert_cmd, NULL);
}
/*
 * 函数说明: 获取一个数据库连接
 * 参数    : 无
 * 返回值  : 成功返回mysql连接池g_conn数组的下标,失败返回-1
 */
int db_connect()
{
int index; for(index=0; index<NCONNECTS; ) {
if((0 == g_conn[index].is_idle) /* 连接非空闲       */
|| (0 != pthread_mutex_trylock(&g_conn[index].mutex))) {   /* 已被别的线程加锁 */
index = (index+1) % NCONNECTS;
continue;
}
g_conn[index].is_idle = 0; /* 标记连接为非空闲 */
if(0 != pthread_mutex_unlock(&g_conn[index].mutex))
return -1;
break;
}
return index;
}/*
 * 函数说明: 封装mysql_query函数
 * 参数    : query_cmd : 要执行的数据库命令
 *           res_pptr  : 要储存的结果集结构体指针(如果为NULL则不储存)
 * 返回值  : 成功返回0,失败返回-1
 */
int db_query(const char *query_cmd, MYSQL_RES **res_pptr)
{
int index;
MYSQL *conn_ptr; if(-1 == (index = db_connect())) /* 获取一个数据库连接 */
return -1;
conn_ptr = &g_conn[index].my_conn;
if(0 != mysql_query(conn_ptr, query_cmd)) {
DB_ERROR(conn_ptr, "mysql_query");
}
/* 储存查询结果到*res_pptr中 */
if((NULL != res_pptr) && (NULL != (*res_pptr = mysql_store_result(conn_ptr)))) {
DB_ERROR(conn_ptr, "mysql_store_result");
g_conn[index].is_idle = 1; /* 标记连接为空闲 */
return -1;
}
g_conn[index].is_idle = 1; /* 标记连接为空闲 */
return 0;
}void *storeinfo_insert_thread(void *arg)
{
int i;
struct FileStoreInfor_t storeinfo = {
"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"
    , 1, 1, 1, 1, 1, 1}; pthread_detach(pthread_self());
if(-1 == db_thread_init())
pthread_exit(NULL);
for(i=0; i<NTHREAD_INSERTS; i++) {
storeinfo.FileDownloadPri = i;
if(0 != insert_storeinfo(&storeinfo))
pthread_exit(NULL);
g_nmysql_inserts++;
}
++g_nthread_ends;
db_thread_end();
pthread_exit(NULL);
}编译的makefile文件:ELF = ${shell find -name "*.c" -type f | awk '{sub(".c$$", "", $$1); print $$1}'}
CFLAGS = -g -Wall -Werror -DMYSQL_DEBUG
LDFLAGS = -ltcmalloc -lpthread -lmysqlclient_r -I/usr/local/mysql-5.5.21/include -L/usr/local/mysql-5.5.21/lib
all: ${ELF}
clean:
rm -f ${ELF}; \
find -name "*.bak" -exec rm -f {} \;
rem: clean all
我的系统: Linux Redhat 6, 64位
Mysql 版本: 5.5.21
Mysq配置: (取自my.cnf):
 
[client]
password = root
database = ufs 
port = 3306
socket = /tmp/mysql.sock
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16M
max_allowed_packet = 1M
table_open_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
max_connections = 100000
max_user_connections = 100000
innodb_open_files = 100000
skip-host-cache
skip-name-resolve
binlog_format=mixed
server-id = 1
[mysqldump]
quick
max_allowed_packet = 16M[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M[mysqlhotcopy]
interactive-timeout
Mysql C Api

解决方案 »

  1.   

    创建数据库相关语句:
    create database ufs;
    use ufs;create table FileStoreInfor
    (
    FileServerMark          varchar(2),
    CryptVersion            varchar(16),
    UploadTime              varchar(32),
    FileCheckCode           varchar(32),
    FileUploadUser          varchar(32),
    FileUploadIp            varchar(32),
    FileClientMac           varchar(32),
    ChName                  varchar(32),
    AppServerName           varchar(32),
    SourceFileName          varchar(32),
    FileStoreFullPath       varchar(64),
    CryptMask               int,
    FileLength              int,
    FileCurrentLen          int,
    FileState               int,
    DownloadPriSeq          int,
    FileDownloadPri         int 
    );
      

  2.   

    系统相关配置:(取自ulimit -a命令):core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 515223
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 500000
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) 2048
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 4096
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
      

  3.   

    系统最大线程数:
    cat /proc/sys/kernel/threads-max 
    1030446
      

  4.   

    问题是执行这程序老是会有问题,比如修改下宏定义:
    #define NCONNECTS       500
    #define NTHREADS        4096
    #define NTHREAD_INSERTS 1000
    就会出现lost connection错误...或者core dumped...