7.1 Обзор асинхронного интерфейса C API
В этом разделе описывается использование асинхронного интерфейса 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).
Следующие примеры иллюстрируют некоторые типичные схемы вызова. представляет собой асинхронную функцию и ее список аргументов.function(args)
-
Если необходимо выполнить другие обработки во время выполнения операции:
enum net_async_status status; status =
function(args); while (status == NET_ASYNC_NOT_READY) { /* perform other processing */ other_processing (); /* invoke same function and arguments again */ status =function(args); } if (status == NET_ASYNC_ERROR) { /* call failed; handle error */ } else { /* call successful; handle result */ } -
Если нет необходимости выполнять другие обработки во время выполнения операции:
enum net_async_status status; while ((status =
function(args)) == NET_ASYNC_NOT_READY) ; /* empty loop */ if (status == NET_ASYNC_ERROR) { /* call failed; handle error */ } else { /* call successful; handle result */ } -
Если результат успешного/неуспешного выполнения функции не важен, и вы хотите гарантировать только завершение операции:
while (
function(args) != NET_ASYNC_COMPLETE) ; /* empty loop */
Для mysql_next_result_nonblocking() также необходимо учитывать статус NET_ASYNC_COMPLETE_NO_MORE_RESULTS, который указывает, что операция завершилась успешно и больше результатов недоступны. Используйте его так:
while ((status = mysql_next_result_nonblocking()) != NET_ASYNC_COMPLETE) {
if (status == NET_ASYNC_COMPLETE_NO_MORE_RESULTS) {
/* no more results */
}
else if (status == NET_ASYNC_ERROR) {
/* handle error by calling mysql_error(); */
break;
}
}
В большинстве случаев аргументы для асинхронных функций такие же, как и для соответствующих синхронных функций. Исключение составляют 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-объектов, используемых программой, выполните следующие операторы. Замените базу данных или пользователя по своему усмотрению; в этом случае вам также потребуется внести некоторые изменения в программу.
CREATE DATABASE db;
USE db;
CREATE TABLE test_table (id INT NOT NULL);
INSERT INTO test_table VALUES (10), (20), (30);
CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpass';
GRANT ALL ON db.* TO 'testuser'@'localhost';
Создайте файл с именем async_app.cc, содержащий следующую программу. При необходимости настройте параметры подключения.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <mysql.h>
#include <mysqld_error.h>
using namespace std;
/* change following connection parameters as necessary */
static const char * c_host = "localhost";
static const char * c_user = "testuser";
static const char * c_auth = "testpass";
static int c_port = 3306;
static const char * c_sock = "/usr/local/mysql/mysql.sock";
static const char * c_dbnm = "db";
void perform_arithmetic() {
cout<<"dummy function invoked\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
Запустите программу. Результаты должны быть похожими на представленные здесь, хотя вы можете увидеть разное количество dummy
function invoked экземпляров.
dummy function invoked
dummy function invoked
ROW: 10
ROW: 20
dummy function invoked
ROW: 30
No more rows to process.
Для эксперимента с программой добавьте и удалите строки из 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, который инициирует неблокирующую операцию, могут оставаться в использовании до завершения операции позже и не должны повторно использоваться до завершения.
Сжатие протокола не поддерживается для асинхронных функций C API.
© 2025 Oracle
Licensed under the GPLv2 License.