Вопрос блокировки MySQL InnoDB - PullRequest
4 голосов
/ 21 октября 2010

У меня есть вопрос о MySQL InnoDB.Например: у меня создана следующая таблица:

   mysql>CREATE TABLE IF NOT EXISTS `SeqNum`
   (
     `id` varchar(10) NOT NULL,
     `seq_num` BIGINT(30) default 0,
      PRIMARY KEY(`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  Query OK, 0 rows affected (0.00 sec)

  mysql>INSERT IGNORE INTO `SeqNum` VALUES('current',0);
  Query OK, 1 rows affected (0.00 sec)

Теперь у меня есть два подключения mysql к одной и той же базе данных, я называю их как потоки A и B. В потоке A у меня есть следующий оператор SQL:

    mysql> begin;
    Query OK, 0 rows affected (0.00 sec)

    mysql> select `seq_num` from SeqNum where `id`='current' FOR UPDATE;
       +---------+
       | seq_num |
       +---------+
       |       0 | 
       +---------+
       1 row in set (0.01 sec)

и затем я просто оставляю поток A как есть.

В потоке B я хотел бы сделать тот же запрос:

   mysql> begin;
   Query OK, 0 rows affected (0.00 sec)

   mysql>SELECT `current_seq_num` FROM SeqNum WHERE `id` = 'current' FOR UPDATE;

поток B выдаст ошибку MySQL 1205 после истечения времени ожидания блокировки: превышено время ожидания блокировки;попробуйте перезапустить транзакцию.

Это имеет смысл, поскольку threadA устанавливает блокировку 'X' для этой строки, так что поток B НЕ может получить блокировку 'X', пока поток A не снимет блокировку.

Теперь мой вопрос: с точки зрения потока B, как я могу узнать, какой поток / соединение блокирует мой запрос (чтобы получить привилегию 'UPDATE' для таблицы 'SeqNum'), когда MySQL возвращает ошибку 1205?мне?Если threadA ничего не делает после получения блокировки X, и я запускаю «show processlist» в потоке B, все, что у меня есть: несколько потоков со статусом «Sleep» (я предполагаю, что к базе данных подключено более двух потоков),Я не могу определить, какая нить заблокировала мой запрос?

Надеюсь, я четко объяснил вопрос.Спасибо!

Ответы [ 4 ]

7 голосов
/ 18 июля 2011

Плагин InnoDB даст вам четкую картину заблокированных и блокирующих запросов.

Например

SELECT r.trx_id waiting_trx_id,  r.trx_mysql_thread_id waiting_thread,
      r.trx_query waiting_query,
      b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
      b.trx_query blocking_query
FROM       information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b  ON  b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r  ON  r.trx_id = w.requesting_trx_id;

даст вам блокировку и блокировку транзакций. Только у вас должен быть установлен плагин innodb.

4 голосов
/ 27 октября 2010

Вы можете легко определить, используете ли вы более новую версию (InnoDB Plugin).В information_schema есть несколько таблиц, к которым вы можете обратиться:

  • SELECT * FROM information_schema.innodb_trx;
  • SELECT * FROM information_schema.innodb_locks;

InВ таблице innodb_trx должен быть столбец с именем 'trx_mysql_thread_id' (или аналогичный - в MySQL 5.5 это trx_mysql_thread_id).Это идентификатор в SHOW PROCESSLIST.

(Обратите внимание, что innodb_locks назван неправильно. Он будет заполняться только для ожидания блокировки, а не блокировки).

2 голосов
/ 26 ноября 2010

Я думаю, что на этом этапе запрос «ПОКАЗАТЬ ДВИГАТЕЛЬ INNODB STATUS \ G» может решить мою проблему.Вот информация из руководства MySQL: http://dev.mysql.com/doc/refman/5.0/en/innodb-monitors.html#innodb-standard-monitor

запустите этот запрос в потоке B, вы получите поток, который заблокировал ваш запрос в разделе «транзакция»

0 голосов
/ 21 октября 2010

Вы участвуете в транзакции в обоих сеансах, т.е. набрали ли вы

START TRANSACTION

Обычно поведение будет таким, как вы хотите, то есть FOR UPDATE будет просто блокировать, пока блокировка не будет доступна (из-заCOMMIT или ROLLBACK с первой транзакции)

...