mysql的C API编程

mysql的C API编程,第1张

MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中,该参数的描述是这样的:

MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt to read from the server. There are retries if necessary, so the total effective timeout value is three times the option value. You can set the value so that a lost connection can be detected earlier than the TCP/IPClose_Wait_Timeout value of 10 minutes.

也就是说在需要的时候,实际的超时时间会是设定值的 3 倍。但是实际测试后发现实际的超时时间和设置的超时时间一致。

而具体什么时候发生三倍超时,在文档中没有找到。所以对 MySQL 5.7.20 的源码进行了一些分析。

使用 GDB 调试代码找了实际与 mysql server 通信的代码,如下:

其中 vio_read() 函数中,使用 recv 和 poll 来读取报文和做读取超时。net_should_retry() 函数只有在发生 EINTR 时才会返回 true。从这段代码来看是符合测试结果的,并没有对读取进行三次重试。只有在读取 *** 作被系统中断打断时才会重试,但是这个重试并没有次数限制。

从上面代码的分析可以看出,代码的逻辑和文档的描述不符。于是在一顿搜索后,找到了一个 MySQL 的 BUG(Bug #31163)。该 BUG 报告了在 MySQL 5.0 中,MySQL c api 读取的实际超时时间是设置的三倍,与现有文档描述相符。于是对 MySQL 5.0.96 的代码又进行分析。

同样使用 GDB 找到了通信部分的代码。这次找到了重试三次的代码,如下:

这个版本的 MySQL api 的读写超时是直接使用的 setsockopt 设置的。第一次循环,在 A 点发生了第一次超时(虽然注释写的非阻塞,但是客户端的连接始终是阻塞模式的)。然后在 B 点将该 socket 设置为阻塞模式,C 点这里重置 retry 次数。由于设置了 alarm 第二次以后的循环会直接进入 D 点的这个分支,并且判断循环次数。作为客户端时net->retry_count 始终是 1,所以重试了两次,共计进行了 3 次 vioread 后从 E 点退出函数。

由上面的分析可知,MySQL 文档对于该参数的描述已经过时,现在的 MYSQL_OPT_READ_TIMEOUT 并不会出现三倍超时的问题。而 Bug #31163 中的处理结果也是将文档中该参数的描述更新为实际读取超时时间是设定时间的三倍。也许是 MySQL 的维护者们在后续版本更新时忘记更新文档吧。

或者绑定变量,官网例子:

MYSQL_TIME ts

MYSQL_BIND bind[3]

MYSQL_STMT *stmt

strmov(query, "INSERT INTO test_table(date_field, time_field,

timestamp_field) VALUES(?,?,?")

stmt = mysql_stmt_init(mysql)

if (!stmt)

{

fprintf(stderr, " mysql_stmt_init(), out of memory\n")

exit(0)

}

if (mysql_stmt_prepare(mysql, query, strlen(query)))

{

fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed")

fprintf(stderr, "\n %s", mysql_stmt_error(stmt))

exit(0)

}

/* set up input buffers for all 3 parameters */

bind[0].buffer_type= MYSQL_TYPE_DATE

bind[0].buffer= (char *)&ts

bind[0].is_null= 0

bind[0].length= 0

...

bind[1]= bind[2]= bind[0]

...

mysql_stmt_bind_param(stmt, bind)

/* supply the data to be sent in the ts structure */

ts.year= 2002

ts.month= 02

ts.day= 03

ts.hour= 10

ts.minute= 45

ts.second= 20

mysql_stmt_execute(stmt)

通过MySQL自定义的API函数进行连接

1、使用API的方式连接,需要加载mysql的头文件和lib文件。

在VS2010的附加包含目录中添加\MySQL\MySQL Server 5.1\include。在安装MySql的目录下找。 把libmysql.dll和libmysql.lib文件拷贝到所建的工程目录下。然后在头文件里包含以下内容:

//mysql所需的头文件和库文件

#include "winsock.h"

#include "mysql.h"

#pragma comment(lib,"libmySQL.lib")

2、进行编码

(1)连接mysql数据库

头文件里定义数据源指针 MYSQL m_sqlCon

//连接MySql数据库

try

{

mysql_init(&m_sqlCon)

// localhost:服务器 root为账号密码 test为数据库名 3306为端口

if(!mysql_real_connect(&m_sqlCon, "localhost","root","root","test",3306,NULL,0))

{

AfxMessageBox(_T("数据库连接失败!"))

return FALSE

}

return TRUE

}

catch (...)

{

return FALSE

}

(2)关闭数据库

mysql_close(&m_sqlCon)

(3)创建表

char* pQuery = "create table if not exists DS_Building( ID VARCHAR(10),Name VARCHAR(255),Descs VARCHAR(255),PRIMARY KEY (ID))"

if(mysql_real_query(&m_sqlCon,pQuery,(UINT)strlen(pQuery))!=0)

{

const char* pCh = mysql_error(&m_sqlCon)

return FALSE

}

附MySQL的API接口:

mysql_affected_rows() 返回被最新的UPDATE, DELETE或INSERT查询影响的行数。

mysql_close() 关闭一个服务器连接。

mysql_connect() 连接一个MySQL服务器。该函数不推荐;使用mysql_real_connect()代替。

mysql_change_user() 改变在一个打开的连接上的用户和数据库。

mysql_create_db() 创建一个数据库。该函数不推荐;而使用SQL命令CREATE DATABASE。

mysql_data_seek() 在一个查询结果集合中搜寻一任意行。

mysql_debug() 用给定字符串做一个DBUG_PUSH。

mysql_drop_db() 抛弃一个数据库。该函数不推荐;而使用SQL命令DROP DATABASE。

mysql_dump_debug_info() 让服务器将调试信息写入日志文件。

mysql_eof() 确定是否已经读到一个结果集合的最后一行。这功能被反对mysql_errno()或mysql_error()可以相反被使用。

mysql_errno() 返回最近被调用的MySQL函数的出错编号。

mysql_error() 返回最近被调用的MySQL函数的出错消息。

mysql_escape_string() 用在SQL语句中的字符串的转义特殊字符。

mysql_fetch_field() 返回下一个表字段的类型。

mysql_fetch_field_direct () 返回一个表字段的类型,给出一个字段编号。

mysql_fetch_fields() 返回一个所有字段结构的数组。

mysql_fetch_lengths() 返回当前行中所有列的长度。

mysql_fetch_row() 从结果集合中取得下一行。

mysql_field_seek() 把列光标放在一个指定的列上。

mysql_field_count() 返回最近查询的结果列的数量。

mysql_field_tell() 返回用于最后一个mysql_fetch_field()的字段光标的位置。

mysql_free_result() 释放一个结果集合使用的内存。

mysql_get_client_info() 返回客户版本信息。

mysql_get_host_info() 返回一个描述连接的字符串。

mysql_get_proto_info() 返回连接使用的协议版本。

mysql_get_server_info() 返回服务器版本号。

mysql_info() 返回关于最近执行得查询的信息。

mysql_init() 获得或初始化一个MYSQL结构。

mysql_insert_id() 返回有前一个查询为一个AUTO_INCREMENT列生成的ID。

mysql_kill() 杀死一个给定的线程。

mysql_list_dbs() 返回匹配一个简单的正则表达式的数据库名。

mysql_list_fields() 返回匹配一个简单的正则表达式的列名。

mysql_list_processes() 返回当前服务器线程的一张表。

mysql_list_tables() 返回匹配一个简单的正则表达式的表名。

mysql_num_fields() 返回一个结果集合重的列的数量。

mysql_num_rows() 返回一个结果集合中的行的数量。

mysql_options() 设置对mysql_connect()的连接选项。

mysql_ping() 检查对服务器的连接是否正在工作,必要时重新连接。

mysql_query() 执行指定为一个空结尾的字符串的SQL查询。

mysql_real_connect() 连接一个MySQL服务器。

mysql_real_query() 执行指定为带计数的字符串的SQL查询。

mysql_reload() 告诉服务器重装授权表。

mysql_row_seek() 搜索在结果集合中的行,使用从mysql_row_tell()返回的值。

mysql_row_tell() 返回行光标位置。

mysql_select_db() 连接一个数据库。

mysql_shutdown() 关掉数据库服务器。

mysql_stat() 返回作为字符串的服务器状态。

mysql_store_result() 检索一个完整的结果集合给客户。

mysql_thread_id() 返回当前线程的ID。

mysql_use_result() 初始化一个一行一行地结果集合的检索。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/8629837.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-19
下一篇 2023-04-19

发表评论

登录后才能评论

评论列表(0条)

保存