MYSQL: Превышено время ожидания блокировки; попробуйте перезапустить транзакцию - PullRequest
1 голос
/ 05 августа 2020

Факты :

  • У меня есть база данных mysql с именем таблицы tableA
  • Я запускаю несколько пакетов aws в в то же время, когда каждый пакетный процесс связывается с tableA посредством:
    • сначала добавляя несколько строк в таблицу
    • затем, удаляя несколько строк в таблице
  • Каждый пакет обрабатывает свой собственный набор строк
  • Если я запускаю один пакетный процесс, проблем не возникает.
  • Когда несколько пакетных процессов выполняются одновременно, появляется следующая ошибка:
    • sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1205, 'Lock wait timeout exceeded; try restarting transaction')
  • Это не связано с пакетом aws, так как та же проблема возникает, когда я пытаюсь сделать это локально.

Дополнительная информация :

  • SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation, @@session.transaction_isolation; ==> repeatable-read, repeatable-read, repeatable-read
  • show variables like 'innodb_lock_wait_timeout' ==> 50

Вопрос

Я вижу, что некоторые решения рекомендуют установить innodb_lock_wait_timeout на более высокое значение, что, вероятно, устранит ошибку. Но я понимаю, что если я установлю innodb_lock_wait_timeout на более высокое значение, то произойдет то, что каждая транзакция будет просто ждать, пока другая транзакция завершит sh. Это означает, что эти процессы не будут выполняться параллельно, поскольку каждый будет ждать другого.

Я хочу, чтобы эти процессы выполнялись без ожидания других транзакций (вставок или удалений), которые происходят в данный момент.

Есть рекомендации?

Ответы [ 2 ]

1 голос
/ 05 августа 2020
  1. Вообще говоря, Repeatable Read - не лучший вариант по умолчанию для производства. Он блокирует все затронутые строки. Это создаст множество ненужных блокировок. Переход на Read Committed значительно снизит количество блокировок.

  2. Перед другой настройкой я предлагаю вам включить журнал блокировок innodb, чтобы увидеть, какие блокировки. set innodb_status_output = on

Если эту блокировку можно снять, это значительно повысит производительность.

Не рекомендую увеличивать innodb_lock_wait_timeout. Если блокировка удерживается более 50 секунд, пакетное задание не будет быстрым.

В худшем сценарии, с которым я сталкивался раньше, если база данных используется другим приложением, например, приложением serer а длительный тайм-аут ожидания может занять все ваши соединения. Это приведет к тому, что ваш сервер приложений не сможет обслуживать новые запросы.

1 голос
/ 05 августа 2020

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

Ускорьте запросы DELETE, используемые в вашем пакетном процессе. Запустите для них EXPLAIN, чтобы убедиться, что у них есть нужные индексы, затем добавьте нужные индексы.

Попробуйте использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; перед запуском пакета в каждом сеансе. Если каждый пакет обрабатывает свой собственный отдельный набор строк, это может (или не может) позволить немного больше параллелизма.

Попробуйте уменьшить размер (количество строк) пакетов. Причина повышения производительности при использовании пакетов транзакций состоит в том, чтобы избежать дорогостоящего выполнения COMMIT для каждой строки. Вы получаете наибольшее повышение производительности с пакетами из 100 строк, как и с пакетами из 10 000 строк.

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

 CREATE TEMPORARY TABLE batchrows;
 INSERT INTO batchrows (col,col,col) VALUES(a,b,c);
 INSERT INTO batchrows (col,col,col) VALUES(d,e,f);
 INSERT INTO batchrows (col,col,col) VALUES(g,h,i);
 BEGIN TRANSACTION;
     INSERT INTO maintable SELECT * FROM batchrows;
     DELETE FROM maintable WHERE col IN (SELECT whatever FROM batchrows); /* ??? */
 COMMIT;
 DROP TEMPORARY TABLE batchrows;

Суть этого? Уменьшение истекшего времени, в течение которого удерживается блокировка транзакции.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...