ActiveRecord «Mysql :: Ошибка: превышено время ожидания блокировки» без видимых блокировок - PullRequest
3 голосов
/ 25 января 2011

Rails версия: 2.3.8

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

ActiveRecord::StatementInvalid (Mysql::Error: Lock wait timeout exceeded; try restarting transaction: INSERT INTO `forum_posts` (`forum_topic_id`, `created_at`, `body`, `ancestry`, `updated_at`, `quote_limit`, `user_id`, `ancestry_depth`, `quote_root`) VALUES(1224783, '2011-01-24 19:18:38', 'Post body', '1285704', '2011-01-24 19:18:38', 1, 57931, 1, 1))

ПроверкаЖурнал медленных запросов MySQL показывает эту запись как:

# Time: 110124 11:19:29
# User@Host: db_user[db_user] @ localhost []
# Query_time: 51  Lock_time: 0  Rows_sent: 0  Rows_examined: 0
SET insert_id=0;
INSERT INTO `forum_posts` (`forum_topic_id`, `created_at`, `body`, `ancestry`, `updated_at`, `quote_limit`, `user_id`, `ancestry_depth`, `quote_root`) VALUES(1224783, '2011-01-24 19:18:38', 'Post body', '1285704', '2011-01-24 19:18:38', 1, 57931, 1, 1);

Согласно журналу Rails, ActiveRecord возвратил ошибку из-за тайм-аута ожидания блокировки.Длительная природа этого простого запроса, кажется, также подсказывает.Дело в том, что нигде нет медленного журнала запросов, я не могу найти фактический запрос, который должен занимать много времени для обработки - все они похожи на приведенный выше пример.Кроме того, в этом же журнале ни одна запись не имеет значения Lock_time больше 0.

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

Заранее спасибо.

1 Ответ

4 голосов
/ 06 ноября 2012

Может быть, это поможет: http://www.mysqlperformanceblog.com/2007/02/25/pitfalls-of-converting-to-innodb/

Мы часто рекомендуем нашим клиентам преобразовать их текущую базу данных из таблиц MyISAM в InnoDB.Сама передача в большинстве случаев почти проста, однако приложение может быть прервано из-за новых непредвиденных ошибок. 1205 (ER_LOCK_WAIT_TIMEOUT) Истекло время ожидания блокировки.Транзакция была отменена.1213 (ER_LOCK_DEADLOCK) Блокировка транзакции.Вы должны повторно выполнить транзакцию.

Эти ошибки не сложно обработать, но вы должны знать об этом.Это то, что мы делаем в наших PHP-приложениях:

class mysqlx extends mysqli {

...

  function deadlock_query($query) {
          $MAX_ATTEMPS = 100;
          $current = 0;
          while ($current++ < $MAX_ATTEMPS) {

                  $res = $this->query($query);

                  if(!$res && ( $this->errno== '1205' || $this->errno == '1213'  ) )
                                  continue;
                  else 
                          break;
             }
 } 
...
}

Возможно, вы захотите обрабатывать ER_LOCK_WAIT_TIMEOUT другим способом, особенно для веб-приложений, где долгое ожидание плохо, вы понимаете.

...