介绍如何使用C API异步接口。在本讨论中,异步和非阻塞被用作同义词,同步和阻塞也是如此。
异步C API函数涵盖了从服务器连接读取或写入时可能阻塞的操作:初始连接操作、发送查询、读取结果等等。每个异步函数与其同步对应的函数有相同的名称,加上_nonblocking
后缀:
mysql_fetch_row_nonblocking ()
:异步从结果集中获取下一行。mysql_free_result_nonblocking ()
:异步释放结果集使用的内存。mysql_next_result_nonblocking ()
:在多个结果执行中异步返回/初始化下一个结果。mysql_real_connect_nonblocking ()
:异步连接MySQL服务器。mysql_real_query_nonblocking()
:异步执行指定为计数字符串的SQL查询。mysql_store_result_nonblocking ()
:异步地向客户端检索完整的结果集。
如果存在不需要异步完成或异步函数不适用的操作,应用程序可以混合使用异步函数和同步函数。
以下讨论更详细地描述了如何使用异步C API函数。
所有异步C API函数返回enum net_async_status
价值。返回值可以是以下值之一,表示操作状态:
NET_ASYNC_NOT_READY
操作仍在进行中,尚未完成。net_async_complete.
:操作成功。NET_ASYNC_ERROR
:操作在错误中终止。NET_ASYNC_COMPLETE_NO_MORE_RESULTS
:操作完成,无结果。此状态仅适用于mysql_next_result_nonblocking ()
.
一般来说,要使用异步函数,请执行以下操作:
反复调用函数,直到不再返回状态
NET_ASYNC_NOT_READY
.检查最终状态是否显示成功完成(
net_async_complete.
)或错误(NET_ASYNC_ERROR
).
下面的示例演示了一些典型的调用模式。
表示异步函数及其参数列表。函数
(args.
)
如果希望在操作进行时执行其他处理:
enum net_async_status状态;状态=函数(args.);while (status == NET_ASYNC_NOT_READY){/*执行其他处理*/ other_processing ();/*再次调用相同的函数和参数*/ status =函数(args.);} if (status == NET_ASYNC_ERROR){/*调用失败;else{/*调用成功;处理结果*/}
如果在运行正在进行时无需执行其他处理:
enum net_async_status状态;((状态=函数(args.) == net_async_not_ready);/*空循环*/ if (status == NET_ASYNC_ERROR){/*调用失败;else{/*调用成功;处理结果*/}
如果函数的成功/失败结果不重要,只想确保操作已经完成:
而(函数(args.) != net_async_complete);/*空循环*/
为mysql_next_result_nonblocking ()
,也有必要说明NET_ASYNC_COMPLETE_NO_MORE_RESULTS
状态,表示操作成功完成,没有更多的结果可用。像这样使用它:
if (status == NET_ASYNC_COMPLETE_NO_MORE_RESULTS){/*不再有结果*/}else if (status == NET_ASYNC_ERROR){/*调用mysql_error()处理错误;* /休息;} }
在大多数情况下,异步函数的参数与相应的同步函数的参数相同。异常mysql_fetch_row_nonblocking ()
和mysql_store_result_nonblocking ()
,与同步版本相比,每个版本都有一个额外的参数。有关详细信息,请参见章节7.4.1、“mysql_fetch_row_nonblocking()”,7.4.6节,“mysql_store_result_nonblocking()”.
本节展示了一个c++程序示例,演示了异步C API函数的使用。
要设置程序使用的SQL对象,请执行以下语句。根据需要替换不同的数据库或用户;在这种情况下,您还需要对程序进行一些调整。
创建数据库db;使用数据库;创建表test_table (id INT NOT NULL);INSERT INTO test_table VALUES (10), (20), (30);创建用户testuser @ localhost IDENTIFIED BY 'testpass';GRANT ALL ON db。*“testuser”@“localhost”;
创建一个名为Async_app.cc.
包含以下程序。根据需要调整连接参数。
#include #include #include #include #include 使用namespace std;/ *根据需要更改以下连接参数* / static const char * c_host =“localhost”;static const char * c_user =“testuser”;静态const char * c_auth =“testpass”;静态int c_port = 3306;static const char * c_sock =“/usr/local/mysql/mysql.sock”;static const char * c_dbnm =“db”;void perform_arithmetic(){cout <<“虚拟函数调用\ n”;for(int i = 0; i <1000; i ++)i * i;int main(int argc,char ** argv){mysql * mysql_local; MYSQL_RES *result; MYSQL_ROW row; net_async_status status; const char *stmt_text; if (!(mysql_local = mysql_init(NULL))) { cout<<"mysql_init() failed\n"; exit(1); } while ((status = mysql_real_connect_nonblocking(mysql_local, c_host, c_user, c_auth, c_dbnm, c_port, c_sock, 0)) == NET_ASYNC_NOT_READY) ; /* empty loop */ if (status == NET_ASYNC_ERROR) { cout<<"mysql_real_connect_nonblocking() failed\n"; exit(1); } /* run query asynchronously */ stmt_text = "SELECT * FROM test_table ORDER BY id"; status = mysql_real_query_nonblocking(mysql_local, stmt_text, (unsigned long)strlen(stmt_text)); /* do some other task before checking function result */ perform_arithmetic(); while (status == NET_ASYNC_NOT_READY) { status = mysql_real_query_nonblocking(mysql_local, stmt_text, (unsigned long)strlen(stmt_text)); perform_arithmetic(); } if (status == NET_ASYNC_ERROR) { cout<<"mysql_real_query_nonblocking() failed\n"; exit(1); } /* retrieve query result asynchronously */ status = mysql_store_result_nonblocking(mysql_local, &result); /* do some other task before checking function result */ perform_arithmetic(); while (status == NET_ASYNC_NOT_READY) { status = mysql_store_result_nonblocking(mysql_local, &result); perform_arithmetic(); } if (status == NET_ASYNC_ERROR) { cout<<"mysql_store_result_nonblocking() failed\n"; exit(1); } if (result == NULL) { cout<<"mysql_store_result_nonblocking() found 0 records\n"; exit(1); } /* fetch a row synchronously */ row = mysql_fetch_row(result); if (row != NULL && strcmp(row[0], "10") == 0) cout<<"ROW: " << row[0] << "\n"; else cout<<"incorrect result fetched\n"; /* fetch a row asynchronously, but without doing other work */ while (mysql_fetch_row_nonblocking(result, &row) != NET_ASYNC_COMPLETE) ; /* empty loop */ /* 2nd row fetched */ if (row != NULL && strcmp(row[0], "20") == 0) cout<<"ROW: " << row[0] << "\n"; else cout<<"incorrect result fetched\n"; /* fetch a row asynchronously, doing other work while waiting */ status = mysql_fetch_row_nonblocking(result, &row); /* do some other task before checking function result */ perform_arithmetic(); while (status != NET_ASYNC_COMPLETE) { status = mysql_fetch_row_nonblocking(result, &row); perform_arithmetic(); } /* 3rd row fetched */ if (row != NULL && strcmp(row[0], "30") == 0) cout<<"ROW: " << row[0] << "\n"; else cout<<"incorrect result fetched\n"; /* fetch a row asynchronously (no more rows expected) */ while ((status = mysql_fetch_row_nonblocking(result, &row)) != NET_ASYNC_COMPLETE) ; /* empty loop */ if (row == NULL) cout <<"No more rows to process.\n"; else cout <<"More rows found than expected.\n"; /* free result set memory asynchronously */ while (mysql_free_result_nonblocking(result) != NET_ASYNC_COMPLETE) ; /* empty loop */ mysql_close(mysql_local); }
使用类似的命令编译程序;根据需要调整编译器和选项:
gcc - g async_app。cc -std=c++11 \ -I/usr/local/mysql/include \ -o async_app -L/usr/lib64/ -lstdc++ \ -L/usr/local/mysql/lib/ -lmysqlclient . conf
运行这个程序。结果应该与您在这里看到的类似,尽管您可能会看到不同数量的虚函数调用
实例。
dummy function invoked dummy function invoked ROW: 10 ROW: 20 dummy function invoked ROW: 30没有更多的行需要处理。
要试验该程序,可以在test_table
,每次更改后重新运行该程序。
这些限制适用于异步C API函数的使用:
mysql_real_connect_nonblocking ()
只能用于与其中一个身份验证插件进行身份验证的帐户:mysql_native_password
,sha256_password
,或caching_sha2_password
.mysql_real_connect_nonblocking ()
只能用于建立TCP/IP或Unix套接字文件连接。传递给发起非阻塞操作的异步C API调用的输入参数可以一直使用,直到该操作稍后终止,并且在终止发生之前不应该被重用。
异步C API函数不支持协议压缩。