Параллельное чтение-запись InnoDB

Я хотел понять, как InnoDB обрабатывает несколько одновременных операций чтения/записи. Рассмотрим следующий сценарий: вы выполняете довольно интенсивную пакетную запись. Любой поступивший запрос на чтение должен будет дождаться завершения пакетной записи. В это время в таблице также запрашивается запрос на запись. Таким образом, к моменту завершения пакетной записи имеется несколько ожидающих запросов на чтение и запись. В каком порядке innodb будет разрешать запросы. В большинстве случаев я бы предпочел получить самый последний набор результатов из таблицы. Таким образом, ожидание запросов на запись было бы правильным, однако это может привести к голоданию запросов на чтение. Все запросы на запись не являются запросами на обновление строк. Я считаю, что запросы на обновление получают блокировку на уровне строки, тогда как запросы на вставку требуют блокировки на уровне таблицы.

Не могли бы вы объяснить, как это будет происходить в InnoDB? Спасибо


person learningMyWayThru    schedule 11.05.2015    source источник


Ответы (2)


В InnoDB INSERTs не блокировка таблицы. (MyISAM — это отдельная история.)

Грубо говоря, каждое чтение или запись в таблицу InnoDB блокирует только необходимые строки. Если между строками одного запроса и другого нет перекрытия, то ожидания нет. Некоторые проблемы, которые делают это «примерно»:

  • Некоторые замки являются замками с промежутком. Подумайте о INSERTing новой строке между двумя существующими строками.
  • Общие блокировки чтения (в одной строке) не блокируют друг друга
  • Блокировки eXclusive действуют примерно так, как вы описали.

"MVCC" позволяет нескольким транзакциям "видеть" разные версии одной и той же строки. Допустим, одна транзакция может быть SELECTing одной строкой, а другая — UPDATEing ей. Пока обе транзакции не будут завершены, физически существует две версии этой строки. Вещи очищаются после того, как обе транзакции будут COMMITed или ROLLBACKed.

Может ничего не стоить то, что все эти блокировки и проверки на уровне строк обходятся дорого. Если у вас работают десятки соединений, все они будут замедляться. В старых версиях 4-8 соединений были практическим пределом. Для 5.7 можно обрабатывать около 64. Тем не менее, InnoDB может обрабатывать тысячи транзакций в секунду, что в конечном итоге ограничивается медленным дисковым вводом-выводом.

«Пакетная вставка» — если вы действительно имеете в виду INSERT в одну таблицу, то оптимально создать один оператор INSERT, содержащий 100-1000 строк. Это уменьшает накладные расходы на связь, синтаксический анализ, оптимизацию и транзакционные издержки. Это также увеличивает риск столкновения при чтении, но ускорение (обычно) перевешивает задержку столкновения.

Обязательно проверяйте наличие ошибок после каждого оператора InnoDB. Могут возникнуть взаимоблокировки. Как правило, они обрабатываются ROLLBACK плюс перезапуск BEGIN...COMMIT.

person Rick James    schedule 11.05.2015

Это сильно зависит от того, делаете ли вы обновления в транзакциях или нет. Вы также можете установить уровень изоляции, чтобы при необходимости увеличить пропускную способность. Это хорошее объяснение: https://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-model.html.

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

person Barry Keepence    schedule 11.05.2015