MySQL: тупик в одной таблице ОБНОВЛЕНИЕ... ГДЕ

Следующая проблема возникает с этой конфигурацией:

  • MySQL 5.7.10
  • Весна 4.0.5
  • Spring Batch 3.0.1
  • Spring ThreadPoolTaskExecutor от 10 до 20 потоков

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

Таблица является:

CREATE TABLE IF NOT EXISTS `invoice_events` (
  `INTERNAL_ID` bigint(20) NOT NULL,
  `FECHA_FAC` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `PERIOD_TYPE` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `PRODUCT_ID` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `RATE_ID` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `INVOICE_INTERNAL_ID` bigint(20) unsigned DEFAULT NULL,
  `COUNTRY_CODE` varchar(4) COLLATE utf8_spanish_ci DEFAULT NULL,
  `SOURCE_MSISDN` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `TARGET_MSISDN` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
  `CATEGORY` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `SERVICE` varchar(50) COLLATE utf8_spanish_ci DEFAULT NULL,
  `USAGE_TYPE` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `BT_COST` double(22,6) DEFAULT NULL,
  PRIMARY KEY (`INTERNAL_ID`,`FECHA_FAC`),
  KEY `IDX_INV_INT_ID` (`INVOICE_INTERNAL_ID`),
  KEY `IDX_MSISDN` (`SOURCE_MSISDN`),
  KEY `IDX_FECHA_FAC` (`FECHA_FAC`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci
PARTITION BY RANGE( TO_DAYS(FECHA_FAC) ) (
    PARTITION p201511 VALUES LESS THAN (TO_DAYS('2015-12-01')),
    PARTITION p201512 VALUES LESS THAN (TO_DAYS('2016-01-01')),
    PARTITION p201601 VALUES LESS THAN (TO_DAYS('2016-02-01')),
    PARTITION p201602 VALUES LESS THAN (TO_DAYS('2016-03-01')),
    PARTITION p201603 VALUES LESS THAN (TO_DAYS('2016-04-01')),
    PARTITION p201604 VALUES LESS THAN (TO_DAYS('2016-05-01')),
    PARTITION p201605 VALUES LESS THAN (TO_DAYS('2016-06-01')),
    PARTITION p201606 VALUES LESS THAN (TO_DAYS('2016-07-01')),
    PARTITION p201607 VALUES LESS THAN (TO_DAYS('2016-08-01')),
    PARTITION p201608 VALUES LESS THAN (TO_DAYS('2016-09-01')),
    PARTITION p201609 VALUES LESS THAN (TO_DAYS('2016-10-01')),
    PARTITION p201610 VALUES LESS THAN (TO_DAYS('2016-11-01')),
    PARTITION p201611 VALUES LESS THAN (TO_DAYS('2016-12-01')),
    PARTITION future VALUES LESS THAN MAXVALUE
  );

Оператор UPDATE:

update invoice_events  
set invoice_internal_id = 978202
where fecha_fac between '2016-02-01 00:00:00' and '2016-05-31 23:59:59.999' 
and source_msisdn = '239642983472' 
and invoice_internal_id is null  
and country_code = 'ES';

Объяснение MySQL для этого утверждения:

ПОКАЗАТЬ СТАТУС ДВИГАТЕЛЯ выпуска:

2016-06-03 11:08:23 0x7f8bcc1aa700
*** (1) TRANSACTION:
TRANSACTION 7031093, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 406 lock struct(s), heap size 41168, 2884 row lock(s), undo log entries 375
MySQL thread id 4726, OS thread handle 140238271616768, query id 10226209 172.30.6.9 BDUSER updating
update invoice_events  set invoice_internal_id = 978173 where fecha_fac between '2016-02-01 00:00:00' and '2016-05-31 23:59:59.999' and source_msisdn in ( '239642983345' )  and invoice_internal_id is null  and country_code = 'ES'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12252 page no 54015 n bits 512 index IDX_MSISDN of table `my_schema`.`invoice_events` /* Partition `p201603` */ trx id 7031093 lock_mode X waiting
Record lock, heap no 101 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 16; hex 33303835303732313033323532303132; asc 3085072103252012;;
 1: len 8; hex 80000000005d2fa3; asc      ]/ ;;
 2: len 5; hex 9998fe0000; asc      ;;

*** (2) TRANSACTION:
TRANSACTION 7031094, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999
mysql tables in use 1, locked 1
424 lock struct(s), heap size 41168, 3945 row lock(s), undo log entries 628
MySQL thread id 4731, OS thread handle 140238401480448, query id 10226408 172.30.6.9 BDUSER updating
update invoice_events  set invoice_internal_id = 978202 where fecha_fac between '2016-02-01 00:00:00' and '2016-05-31 23:59:59.999' and source_msisdn in ( '239642983472' )  and invoice_internal_id is null  and country_code = 'ES'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 12252 page no 54015 n bits 512 index IDX_MSISDN of table `my_schema`.`invoice_events` /* Partition `p201603` */ trx id 7031094 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Из переменных базы данных innodb я замечаю, что значение innodb_thread_concurrency равно 32.

Выбранные разделы содержат 21853907 строк.

Я попытался сделать простое заявление ОБНОВЛЕНИЕ. Я фильтрую через fecha_fac только для доступа к необходимым разделам, а затем фильтрую по индексированным полям.

Итак, мой первый и главный вопрос: как я могу исправить эту блокировку транзакции? Любой совет, совет, ...?

Любые другие важные вопросы:

  • Из вывода EXPLAIN: может ли тип (диапазон) быть лучше даже при обновлении одной таблицы? Или это лучший тип, возможный для обновления за одной таблицей?
  • Из вывода EXPLAIN: правильно ли, что конечный ключ был IDX_INV_INT_ID вместо IDX_MSISDN? IDX_INV_INT_ID индексирует пустой столбец.
  • Помогает ли параметр innodb_thread_concurrency установить значение 0 (бесконечный параллелизм)?
  • Есть ли какие-либо данные в выводе SHOW STATUS, которые могли бы мне помочь, а я не заметил?

В дополнение к моим вопросам, любая помощь или совет очень ценятся.

Заранее спасибо.

1 ответ

Как предложил @Shadow, я просмотрел индексы, и остался только IDX_MSISDN.

Другие полезные практики для разработки БД и предотвращения тупиков, которые я сделал:

  • Изменить порядок столбцов. Возможные NULL и / или неиндексированные столбцы перенесены в конец.
  • Установите тип и размер данных столбца с помощью ПРОЦЕДУРЫ АНАЛИЗА (). Например, SOURCE_MSISDN был уменьшен, поэтому key_len также уменьшен.
  • Синхронизированные транзакции. Выполняется только одна транзакция для элемента Spring Batch. В моем дизайне пропускная способность снизилась примерно на 5-10%, и это управляемо.

Надеюсь, поможет.

Другие вопросы по тегам