Как избежать многократного использования mysql_real_connect() для каждого запроса?

Я запрашиваю свою базу данных через коннектор, который я сделал в Lazarus/Freepascal. Он использует libmysql из MySQL 5.0. Насколько я могу судить, функции, которые я могу вызывать, идентичны функциям MYSQL C Connector.

База данных не предназначена для удаленного доступа; это доступная по каналу база данных, которую я пытаюсь оптимизировать для локального чтения, используя таблицы только для памяти (без MyISAM или InnoDB). Скорость является основным направлением.

Клиентское приложение написано на ограниченном языке сценариев под названием MQL4 (для финансовых рынков) и использует мою библиотеку для повторных запросов к базе данных и возврата результатов для анализа.

Проблема в следующем: я вынужден уничтожать и заново создавать соединение с базой данных каждый раз, когда отправляю новый запрос.

Если я не уничтожу и не создам соединение заново, я получу нарушение доступа для чтения, потому что моя библиотека коннекторов потеряет значение *MYSQL, назначенное mysql_real_connect().

Я бы передал это значение через свое клиентское приложение, но, к сожалению, оно написано на языке, который может обрабатывать только типы данных LongInt, Double и String.

Я попытался передать значение через приведение клиентского приложения к LongInt, а затем вернуть его *MYSQL в свою библиотеку, но это не сработало.

Честно говоря, я не понимаю, почему моя библиотека теряет значение для *MYSQL.

Вот код моей библиотеки:

{$CALLING STDCALL}

library D1Query;

{$mode objfpc}{$H+}

uses
  cmem, Windows, SysUtils, mysql50;

var
  sock: PMYSQL;
  qmysql: st_mysql;

type
  VArray = array[0..100] of Double;
  PArray = ^VArray;

  procedure InitSQL; stdcall;
  begin
    sock := mysql_real_connect(PMysql(@qmysql), '.', 'root', 'password'
                     , 'data', 3306, 'mysql', CLIENT_MULTI_STATEMENTS);
    if sock = nil then begin
      OutputDebugString(PChar('  Couldn''t connect to MySQL.'));
      OutputDebugString(PChar(mysql_error(@qmysql)));
      halt(1);
    end;
  end;

  procedure DeInitSQL; stdcall;
  begin
    mysql_close(sock);
  end;

  function SQL_Query(QRY: PChar; output: PArray): integer; stdcall;
  var
    rowbuf: MYSQL_ROW;
    recbuf: PMYSQL_RES;
    i: integer;
    nfields: LongWord;
  begin
    if (mysql_query(sock, QRY) < 0) then begin
      OutputDebugString(PChar('  Query failed '));
      OutputDebugString(PChar('   ' + mysql_error(sock)));
    end;

    recbuf := mysql_store_result(sock);
    nfields :=  mysql_num_fields(recbuf);
    rowbuf := mysql_fetch_row(recbuf);

    if (rowbuf <> nil) then begin
      for i:=0 to nfields-1 do
          output^[i] := StrToFloatDef(rowbuf[i], -666);
    end;

    mysql_free_result(recbuf);
    Result := i;   
  end;

exports
  SQL_Query, InitSQL, DeInitSQL;

begin
end.

person Mike Furlender    schedule 27.05.2011    source источник
comment
Я переключил mysql_connect на mysql_real_connect и использовал mysql_error, чтобы найти проблему. Вот что я получил: [2448] error: Lost connection to MySQL server during query Итак, сервер разрывает мое соединение... Есть ли способ установить постоянные соединения, которые разрешают выполнение хранимых процедур?   -  person Mike Furlender    schedule 28.05.2011
comment
Пробовали ли вы ZEOS подключаться к MySQL? wiki.lazarus.freepascal.org/Zeos_tutorial   -  person Johan    schedule 28.05.2011
comment
ДОЛЖЕН быть способ, которым вы прикрепляете запрос к открытому соединению, поэтому избегаете соединения для каждого запроса, однако все зависит от реализации библиотеки, пожалуйста, прочитайте SDK или файл(ы) справки, ИМХО запрос ничего не значит больше, чем способ отправки и получения данных, когда вы устанавливаете соединение с базой данных, дескриптор соединения ДОЛЖЕН быть возвращен где-то, который может быть повторно использован в будущем, однако это также зависит от реализации библиотека, которую вы используете.   -  person    schedule 28.05.2011
comment
Привет. Вот что я нашел, возможно, это может вас заинтересовать: Обратите внимание, что при подключении mysql_real_connect() устанавливает флаг повторного подключения (часть структуры MYSQL) в значение 1 в версиях API старше 5.0.3 или 0 в новых версиях. Значение этого флага, равное 1, указывает на то, что если оператор не может быть выполнен из-за потери соединения, необходимо попытаться повторно подключиться к серверу, прежде чем сдаваться. Начиная с MySQL 5.0.13, вы можете использовать параметр MYSQL_OPT_RECONNECT в mysql_options() для управления поведением повторного подключения.   -  person Pateman    schedule 29.05.2011


Ответы (1)


Майк, я бы рекомендовал использовать ZEOS 6.6.6 для подключения к MySQL.

Таким образом, вам не нужно копаться в низкоуровневом коде, а можно просто использовать стандартные элементы управления ZEOS: TZConnection TZQuery и т. д.

Вот руководство по использованию ZEOS в Lazarus: http://wiki.lazarus.freepascal.org/Zeos_tutorial
Пакет ZEOS можно загрузить
здесь: http://sourceforge.net/projects/zeoslib/files/Zeos%20Database%20Objects/zeosdbo-6.6.6-stable/ZEOSDBO-6.6.6-stable.zip/download
Загрузите zip-файл и установите пакет для Lazarus.

Файлы справки можно найти здесь: http://sourceforge.net/projects/zeoslib/files/Zeos%20Database%20Objects/zeosdbo-6.6.6-stable/

Удачи.

person Johan    schedule 29.05.2011