MySQL переподключить с ++ - PullRequest
1 голос
/ 08 августа 2011

Прямо сейчас у меня есть клиентское приложение C ++, которое использует mysql.h для подключения к базе данных MYSQL, и мне нужно предварительно настроить логику на случай отключения.Мне интересно, если это лучший способ восстановить соединение с базой данных MYSQL в ситуации, когда мой клиент отключается.

bool MYSQL::Reconnect(const char *host, const char *user, const char *passwd, const char *db)
{
bool out = false;

pid_t command_pid = fork();
if (command_pid == 0)
{
    while(1)
    {
        sleep(1);
        if (mysql_real_connect(&m_mysql, host, user, passwd, db, 0, NULL, 0) == NULL )
        {
            fprintf(stderr, "Failed to connect to database: Error: %s\n",
            mysql_error(&m_mysql));
        }
        else
        {
            m_connected = true;
            out = true;
            break;
        }
    }
    exit(0);
}

if (command_pid < 0)
    fprintf(stderr, "Could not fork process[reconnect]: %s\n", mysql_error(&m_mysql));

return out;
}

Прямо сейчас я беру все свои параметры и готовлю форк.дочерний процесс пытается каждую секунду переподключаться с помощью оператора sleep ().Это хороший способ сделать это?Спасибо

Ответы [ 3 ]

4 голосов
/ 10 августа 2011

Извините, но ваш код не работает так, как вы думаете, кайзер Вильгельм.

По сути, вы пытаетесь рассматривать вилку как нить, которой она не является.

Когда вы разветвляете дочерний процесс, родительский процесс полностью клонируется, включая дескрипторы файлов и сокетов, и именно так ваша программа подключается к серверу базы данных MySQL. Таким образом, и родительский, и дочерний элементы получают собственную копию одного и того же соединения с сервером базы данных при вилке. Я предполагаю, что родитель вызывает этот Reconnect() метод только тогда, когда видит сбой соединения и перестает использовать свою копию теперь не существующего объекта соединения MySQL, m_mysql. Если это так, родительская копия соединения становится такой же бесполезной, как и копия клиента, когда вы запускаете операцию повторного соединения.

Дело в том, что обратное также неверно: как только дочернему элементу удается повторно подключиться к серверу базы данных, родительский объект подключения остается несуществующим. Ничто из того, что делает ребенок, не распространяется обратно до родителя. После разветвления эти два процесса полностью независимы, за исключением тех случаев, когда они могут пытаться получить доступ к некоторым ресурсам ввода-вывода, которые они первоначально совместно использовали. Например, если вы назвали это Reconnect(), когда соединение было установлено и продолжало использовать соединение в родительском, попытки ребенка связаться с сервером БД по тому же соединению могли бы спутать либо mysqld, либо libmysqlclient, что может привести к повреждение данных или сбой.

Как указывалось выше, одним из решений этой проблемы является использование потоков вместо разветвления. Однако остерегайтесь многих проблем с использованием потоков с MySQL C. API.

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

Кажется, вы пытаетесь избежать блокировки основного потока приложения при попытке переподключения сервера БД. Может случиться так, что вам все равно удастся выполнить это синхронно, установив , установив тайм-аут соединения на 1 секунду, что хорошо, когда сервер MySQL находится на той же машине или в той же локальной сети, что и клиент. Если вы можете допустить блокировку основного потока на время до секунды для попыток соединения потерпеть неудачу & mdash; наихудший случай происходит, когда сервер находится на отдельной машине, и он физически отключен или защищен брандмауэром & mdash; это, вероятно, будет более чистым решением, чем темы. Попытка подключения может потерпеть неудачу гораздо быстрее, если серверный компьютер все еще работает, а порт не защищен брандмауэром, например, когда он перезагружается и стек TCP / IP все еще активен.

0 голосов
/ 10 августа 2011

Насколько я могу судить, это не делает то, что вы хотели.

Логические проблемы

Reconnect не "выполняет некоторую логику в случае отключения"на всех.

Он пытается подключиться снова и снова, пока не получится, затем останавливается.Вот и все.Состояние соединения никогда не проверяется снова.Если соединение обрывается, этот код не знает ничего об этом.

Технические проблемы

Также обратите пристальное внимание на технические проблемы, возникающие у Уоррена.

0 голосов
/ 08 августа 2011

Конечно, все в порядке. Возможно, вы захотите подумать о замене цикла while ( 1 ) чем-то вроде

  while ( NULL == mysql_real_connect( ... )) {
    sleep( 1 );
    ... 
  }

это та идиома, которую изучают на практике, но, насколько я понимаю, ваш код работает просто отлично. Не забудьте поставить счетчик внутри цикла while.

...