Spec-Zone.ru › MySQL Connectors 1.0

7.1 Обзор асинхронного интерфейса C API

В этом разделе описывается использование асинхронного интерфейса C API. В данном обсуждении асинхронный и неблокирующий используются как синонимы, так же как и синхронный и блокирующий.

Асинхронные функции C API охватывают операции, которые в противном случае могут заблокироваться при чтении или записи из соединения с сервером: начальная операция подключения, отправка запроса, чтение результата и так далее. Каждая асинхронная функция имеет такое же имя, как и её синхронный аналог, плюс суффикс _nonblocking:

  • mysql_fetch_row_nonblocking(): Асинхронно извлекает следующую строку из набора результатов.

  • mysql_free_result_nonblocking(): Асинхронно освобождает память, используемую набором результатов.

  • mysql_get_connect_nonblocking_stage(): Информация о состоянии машины mysql_real_connect_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.8, «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() может использоваться только для учетных записей, которые проходят аутентификацию с использованием 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.
https://docs.oracle.com/cd/E17952_01/c-api-9.2-en/c-api-asynchronous-interface-usage.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API