Необычные проблемы с блокировкой таблиц MySQL

Все мы знаем, что обновления InnoDB блокируют строки, а обновления MyISAM блокируют таблицы, но как вы это объясните? Вот результаты SHOW FULL PROCESSLIST, когда проблема находится в процессе возникновения:

╔═════════╦════════╦═════════╦════════════════════════════════╗
║ Command ║ Time   ║ State   ║ Info                           ║
╠═════════╬════════╬═════════╬════════════════════════════════╣
║ Query   ║ 0      ║ NULL    ║ SHOW FULL PROCESSLIST          ║
║ Query   ║ 121    ║ end     ║ UPDATE [InnoDB table]          ║
║ Query   ║ 121    ║ update  ║ INSERT INTO [MyISAM table]     ║
║ Query   ║ 121    ║ Locked  ║ INSERT INTO [MyISAM table]     ║
║ Query   ║ 120    ║ Locked  ║ INSERT INTO [MyISAM table]     ║
║ Query   ║ 120    ║ Locked  ║ INSERT INTO [MyISAM table]     ║
╚═════════╩════════╩═════════╩════════════════════════════════╝

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

Проблема начинается с UPDATE в таблице InnoDB, которая затем блокирует таблицу MyISAM. База данных в целом не заблокирована, поскольку каждую секунду выполнялись сотни запросов SELECT, и они не зависали. Обратите внимание, что состояние первого INSERT — «обновление», что, по-видимому, является причиной блокировки последующих вставок, но тогда возникает вопрос: что такое обновление INSERT? Автоинкремент? Индексы таблиц? Предположительно. Но почему такое обновление блокируется ОБНОВЛЕНИЕМ другой таблицы? Подробнее о том, что означают эти состояния, см. здесь:

http://dev.mysql.com/doc/refman/5.1/en/general-thread-states.html

Вот что я понял до сих пор:

  • В запросах нет ничего плохого — UPDATE индексируется соответствующим образом, а запросы INSERT и UPDATE обычно выполняются ‹ 100 мс, но, как вы можете видеть, этот запрос занимает более 2 минут.
  • Почти все запросы, выполняемые к базе данных, являются SELECT и INSERT, за исключением UPDATE.
  • Это определенно ОБНОВЛЕНИЕ, вызывающее проблему, поскольку оно полувоспроизводимо - если я выполняю аналогичный запрос, иногда он воссоздает проблему, иногда он выполняется быстро, как обычно.
  • Только эта конкретная таблица InnoDB кажется проблемой, поскольку другие таблицы InnoDB в базе данных обновляются без проблем, но зато она самая большая - она ​​содержит ~ 1 миллион строк и имеет размер ~ 40 МБ.
  • ОБНОВЛЕНИЕ реплицируется на несколько серверов, но длительное время выполнения, по-видимому, происходит только на серверах со значительной нагрузкой.
  • Я проверил загрузку ЦП и свободную оперативную память на сервере во время возникновения проблемы, и они оба в порядке.

Спецификации сервера:

  • Сжатие Debian
  • MySQL 5.1
  • 8 ядер
  • 32 ГБ ОЗУ

Прежде чем вы спросите, вот некоторые настройки конфигурации [mysqld]:

skip-external-locking
innodb_file_per_table
innodb_flush_method     = O_DIRECT
innodb_buffer_pool_size = 512M
key_buffer              = 1500M
read_rnd_buffer_size    = 512k
table_open_cache        = 4096
tmp_table_size          = 256M
max_heap_table_size     = 256M
concurrent_insert       = 2
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
max_connections         = 2000
open_files_limit        = 60000
query_cache_limit       = 1M
query_cache_size        = 512M

После обширного гугления я все еще в недоумении, поэтому любая помощь будет принята с благодарностью!

Добавлен

Создайте синтаксис для таблицы InnoDB:

CREATE TABLE `tablename` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `column1` bigint(20) unsigned NOT NULL,
  `column2` int(10) unsigned NOT NULL,
  `column3` int(10) unsigned NOT NULL,
  `column4` int(10) unsigned NOT NULL,
  `column5` int(10) unsigned DEFAULT NULL,
  `column6` enum('yes','no') NOT NULL DEFAULT 'no',
  PRIMARY KEY (`id`),
  UNIQUE KEY (`column1`),
  KEY (`column2`),
  KEY (`column5`)
) ENGINE=InnoDB AUTO_INCREMENT=993266 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

person Philip    schedule 06.11.2013    source источник
comment
Являются ли обновления транзакцией или чистым оператором обновления? Какие у вас настройки автофиксации?   -  person Mad Dog Tannen    schedule 06.11.2013
comment
Вы также должны значительно увеличить свой innodb_buffer_pool_size.   -  person Mad Dog Tannen    schedule 06.11.2013
comment
Если все запросы используют одно и то же соединение, это может быть проблемой. Поскольку каждый запрос должен завершиться, прежде чем соединение сможет принять новый.....   -  person Mad Dog Tannen    schedule 06.11.2013
comment
@KayNelson Обновления «чистые», то есть не в транзакции. Автофиксация по умолчанию, поэтому 1. Все запросы используют разные соединения. Я мог бы увеличить размер пула буферов, но общий размер данных InnoDB составляет ~ 70 МБ, поэтому в этом не было особого смысла — если вы не знаете иного?   -  person Philip    schedule 06.11.2013
comment
Не могли бы вы указать определение таблицы и синтаксис обновления?   -  person Mad Dog Tannen    schedule 06.11.2013
comment
@KayNelson Синтаксис обновления: «ОБНОВЛЕНИЕ [имя таблицы] SET [столбец] = [значение столбца] ГДЕ id = [значение_идентификатора]», где id является автоматически увеличивающимся первичным ключом. Когда вы говорите определение таблицы, вы имеете в виду синтаксис CREATE?   -  person Philip    schedule 06.11.2013
comment
Да синтаксис создания   -  person Mad Dog Tannen    schedule 06.11.2013
comment
@KayNelson Хорошо, я добавил это к исходному вопросу.   -  person Philip    schedule 06.11.2013
comment
Возможно, особенно если вы настроили innodb_flush_log_at_trx_commit, запись MyISAM ожидает в конце длинной очереди записи на диск.   -  person symcbean    schedule 07.11.2013
comment
@symcbean Да, мне было интересно об этом. innodb_flush_log_at_trx_commit по умолчанию, поэтому 1. Я полагаю, вы бы предложили установить его на 2? Если бы была длинная очередь записи на диск, ожидали бы вы также увидеть много зависших обновлений в SHOW PROCESSLIST? Только есть только тот.   -  person Philip    schedule 07.11.2013
comment
Кстати: может быть, лучше спросить на DBA.stackexchange.com, а не здесь   -  person symcbean    schedule 07.11.2013
comment
@symcbean Хорошо, спасибо за совет   -  person Philip    schedule 07.11.2013
comment
У меня была мозговая волна в автобусе домой - 121 секунда - это слишком долго, чтобы ждать очистки дискового буфера: может ли блокировка MyISAM быть следствием режима транзакций, являющегося повторяемым чтением / чтением? В отсутствие управления версиями в MyISAM единственным способом обеспечить согласованность наверняка будет блокировка всей таблицы? Может, попробовать READ UNCOMMITTED?   -  person symcbean    schedule 08.11.2013


Ответы (1)


Поскольку ваш статус находится в состоянии «конец». Эти вещи могут произойти

Для конечного состояния могут выполняться следующие операции в соответствии с документация:

◾ Удаление записей кэша запросов после изменения данных в таблице

◾ Запись события в бинарный лог

◾ Освобождение буферов памяти, в том числе для блобов

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

person Mad Dog Tannen    schedule 06.11.2013
comment
Спасибо, звучит правдоподобно - попробую. Я пропустил приведенную выше информацию, так как по какой-то причине она находится в состоянии «инициализация», а не в состоянии «конец»! - person Philip; 07.11.2013
comment
@Philip, есть прогресс? - person Mad Dog Tannen; 08.11.2013
comment
Я реализовал решение, но подожду неделю или две, прежде чем подтвержу, что проблема решена. - person Philip; 08.11.2013
comment
@Philip круто, ты полностью отключил или уменьшил размер кеша? Удачи, надеюсь, это решит вашу проблему! - person Mad Dog Tannen; 08.11.2013
comment
Я решил полностью отключить его, так как в выполняемых запросах SELECT мало повторений, и все они очень быстрые и все равно возвращают только одно поле. Не будучи администратором баз данных, я не думал об этом раньше! - person Philip; 11.11.2013