MySQL Process List - повышение производительности - проблема с блокировкой - PullRequest
1 голос
/ 03 декабря 2011

В SHOW PROCESSLIST - он показывает, что около 30+ строк было заблокировано на несколько секунд, а затем обновлено.

Есть ли способ ускорить его обновление?

Пример:

+------+-----------------+-----------+----------------+---------+------+----------+-------------------------------------------------------------------------------
| Id   | User            | Host      | db             | Command | Time | State    | Info                                                                          
+------+-----------------+-----------+----------------+---------+------+----------+--------------------------------------------------------------------------------
|  265 | user            | localhost | xxxxxxxxxxxxxx | Query   |   15 | Updating | UPDATE data SET status = '1', error = 'Unknown error'  WHERE f= 0xxxxx    
|  269 | user            | localhost | xxxxxxxxxxxxxx | Query   |   17 | Updating | UPDATE data SET status = '1', error = 'Invalid ....'  WHERE f= 0xxx 
|  280 | user            | localhost | xxxxxxxxxxxxxx | Query   |    7 | Updating | UPDATE data SET status = 1  WHERE f = 0xxxx                                           
|  300 | user            | localhost | xxxxxxxxxxxxxx | Query   |    1 | Updating | UPDATE data SET status = '1', error = 'Unknown ....'  WHERE f= 0xx             
|  314 | user            | localhost | xxxxxxxxxxxxxx | Query   |   13 | Updating | UPDATE data SET status = '1', error = 'Invalid....'  WHERE f= 0xxxx
|  327 | user            | localhost | xxxxxxxxxxxxxx | Query   |   11 | Updating | UPDATE data SET status = '1', error = 'Unknown ....'  WHERE f= 0xxxx               
|  341 | user            | localhost | xxxxxxxxxxxxxx | Sleep   |    2 |          | NULL                                                                                        
|  350 | user            | localhost | xxxxxxxxxxxxxx | Query   |    7 | Updating | UPDATE data SET status = '1', error = 'Unknown ....'  WHERE f= 0xxx                
|  360 | user            | localhost | xxxxxxxxxxxxxx | Query   |    5 | Updating | UPDATE data SET status = 1  WHERE f = 0xxxx     

ОБНОВЛЕНИЙ много - я использую InnoDB, некоторые поля index.

В таблице данных необходимо обновить более 500 000 строк, пока она зацикливается в скрипте PHP CLI (выполняется в фоновом режиме / процессе в Linux).

Ответы [ 4 ]

1 голос
/ 03 декабря 2011
  • Убедитесь, что столбец f проиндексирован, поэтому его использует предложение WHERE.В противном случае вы будете сканировать всю таблицу на предмет каждого ОБНОВЛЕНИЯ.

  • Попробуйте сгруппировать обновления, чтобы можно было установить множество строк с одним ОБНОВЛЕНИЕМ вместо одной строки за раз.*

  • Убедитесь, что вы не используете автокоммит.Попробуйте выполнить несколько изменений для каждой транзакции.

  • Убедитесь, что вы настроили InnoDB.Большинство людей используют значения по умолчанию для innodb_buffer_pool_size, innodb_log_file_size и innodb_io_capacity.Значения по умолчанию не настроены для высокой производительности.

  • Установите innodb_flush_log_at_trx_commit=2 для уменьшения fsyncs, как предполагает @Paulo H.

1 голос
/ 03 декабря 2011

InnoDB использует IO в каждом INSERT / UPDATE, чтобы обеспечить свойство de ACID, вы можете изменить это поведение, задав переменную innodb_flush_log_at_trx_commit равной 2, поэтому MySQL использует IO каждую секунду вместо каждой фиксации (довольно хорошо во многих случаях).

Подробнее здесь

0 голосов
/ 03 декабря 2011

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

0 голосов
/ 03 декабря 2011

Быстрое решение состоит в том, чтобы стратегически добавить вызов sleep (), чтобы, перебирая несколько тысяч строк, вы не перегружали базу данных.Хорошая практика - спать по 1/100 секунды для каждого ряда, а затем спать в течение полных 5 секунд на каждые 100 строк.Это общее правило для систем, с которыми я связан, поэтому вам, возможно, придется немного поработать с этими настройками, чтобы заставить их работать на вас.

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

...