Как тайм-аут запроса MySQL в C ++ - PullRequest
6 голосов
/ 17 сентября 2008

Я использую mysql ++ для подключения к базе данных MySQL для выполнения нескольких запросов данных. Из-за того факта, что таблицы, из которых я читаю, постоянно записываются, и что мне необходимо согласованное представление данных, я сначала блокирую таблицы. Тем не менее, MySQL не имеет понятия «NOWAIT» в своем запросе на блокировку, поэтому, если таблицы заблокированы чем-то другим, что удерживает их в течение длительного времени, мое приложение ожидает этого. Я хочу иметь возможность вернуться и сказать что-то вроде «Блокировка не может быть получена» и повторить попытку через несколько секунд. Моя общая попытка этого тайм-аута ниже.

Если я запускаю это после блокировки таблицы в базе данных, я получаю сообщение о том, что истекло время ожидания, но я не знаю, как заставить строку mysql_query завершиться. Буду признателен за любую помощь / идеи!


volatile sig_atomic_t success = 1;

void catch_alarm(int sig) {
        cout << "Timeout reached" << endl;
        success = 0;
        signal(sig,catch_alarm);
}

// connect to db etc.
// *SNIP

signal (SIGALRM, catch_alarm);
alarm(2);
mysql_query(p_connection,"LOCK TABLES XYZ as write");

Ответы [ 7 ]

3 голосов
/ 01 октября 2008

Вы можете реализовать поведение, подобное отмене, таким образом:

Вы выполняете запрос в отдельном потоке, который продолжает работать независимо от того, истекло ли время ожидания. Тайм-аут происходит в главном потоке и устанавливает переменную в «1», отмечая, что это произошло. Затем вы делаете все, что хотите, в своей основной теме.

Поток запроса после его завершения проверяет, истекло ли время ожидания. Если это не так, он выполняет остальную часть работы, которую ему нужно сделать. Если он имеет, он просто разблокирует таблицы, которые он только что заблокировал.

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

0 голосов
/ 19 сентября 2008

Мой опыт, описанный выше, показывает мне, что закрытие соединения, в котором выполняется запрос, вызывает ошибку сегмента. Поэтому отправка этого запроса в другое соединение на самом деле не поможет, так как это также вызовет ошибку.

0 голосов
/ 18 сентября 2008

Я не знаю, является ли это хорошей идеей с точки зрения использования ресурсов, «лучших практик», «чистоты» и всего остального ... но вы уже неоднократно описывали наручники, которые связывают вас с точки зрения -архитектирование "чистой" системы ... вот так .....

Не могли бы вы открыть новое отдельное соединение только для отправки оператора LOCK? Затем закройте это соединение, когда вы ловите тайм-аут? Закрывая / уничтожая соединение, которое было выделено для оператора LOCK, разве это не «отменяет» в действительности утверждение LOCK? Я не уверен, что такие события произойдут, как я описал / предположил, но, возможно, это что-то, что нужно проверить.

0 голосов
/ 18 сентября 2008

Как я уже сказал, не так легко «переключиться» или изменить архитектуру, когда это живая, производственная система. Я немного разочарован тем, что MySQL не предоставляет методов для проверки блокировок или выбора, чтобы не зависать в ожидании блокировки.

0 голосов
/ 17 сентября 2008

вместо того, чтобы пытаться подделывать транзакции с блокировками таблиц, почему бы не переключиться на таблицы innodb, где вы получаете реальные транзакции? просто убедитесь, что для уровня изоляции транзакции по умолчанию установлено значение REPEATABLE READ.

0 голосов
/ 17 сентября 2008

Если бы я писал с нуля, я бы так и сделал, но это серверное приложение, которое мы просто обновляем, а не переделываем.

0 голосов
/ 17 сентября 2008

Вы можете выполнить запрос на блокировку в другом потоке и никогда не беспокоиться о времени ожидания. Когда поступают некоторые данные, вы уведомляете поток, который должен знать о состоянии транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...