Я использую 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");





Вы можете выполнить блокирующий запрос в другом потоке и никогда не беспокоиться о тайм-ауте. Когда поступают некоторые данные, вы уведомляете поток, который должен знать о статусе транзакции.
Если бы я писал с нуля, я бы сделал это, но это серверное приложение, которое мы просто обновляем, а не переделываем.
вместо того, чтобы пытаться подделать транзакции с помощью блокировок таблиц, почему бы не переключиться на таблицы innodb, где вы получаете реальные транзакции? просто убедитесь, что уровень изоляции транзакции по умолчанию установлен на REPEATABLE READ.
Как я уже сказал, не так-то просто «переключить» или изменить архитектуру, когда это живая, в производственной системе. Я немного разочарован тем, что MySQL не предоставляет методов для проверки блокировок или отказа от ожидания блокировки.
Я не знаю, хорошая ли это идея с точки зрения использования ресурсов, «лучших практик», «чистоты» и всего остального ... но вы уже неоднократно описывали наручники, которые связывают вас, с точки зрения изменения архитектуры "чистая" система ... итак .....
Не могли бы вы открыть новое отдельное соединение только для отправки оператора LOCK? Затем закрыть это соединение, когда вы поймаете сигнал тайм-аута? При закрытии / разрушении соединения, которое было выделено для оператора LOCK, не будет ли это по существу "отменить" состояние LOCK? Я не уверен, произойдут ли такие события, как я описал / предположил, но, возможно, это то, что нужно проверить.
Мой опыт, описанный до сих пор, показывает мне, что закрытие соединения, в котором выполняется запрос, вызывает ошибку seg. Поэтому отправка этого запроса в другое соединение на самом деле не поможет, так как это также приведет к возникновению ошибки.
Вы можете реализовать поведение, подобное отмене, следующим образом:
Вы выполняете запрос в отдельном потоке, который продолжает выполняться независимо от того, истекло время ожидания или нет. Тайм-аут происходит в основном потоке и устанавливает для переменной значение «1», обозначающее, что это произошло. Затем вы делаете все, что хотите, в своем основном потоке.
Поток запроса после завершения запроса проверяет, не истек ли тайм-аут. Если этого не произошло, он сделает остальную работу, которую ему нужно сделать. Если БУДЕТ, он просто разблокирует только что заблокированные таблицы.
Я знаю, что это звучит немного расточительно, но период блокировки-разблокировки должен быть в основном мгновенным, и вы получите максимально приближенный к желаемому результату.