Взаимоблокировки Percona XtraDB при вставке с уникальным PK

У меня есть кластер из 3 серверов percona db, и эта таблица:

CREATE TABLE `metric` (
  `metricid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `host` varchar(50) NOT NULL,
  `userid` int(10) unsigned DEFAULT NULL,
  `name` varchar(255) NOT NULL,
  `sampleid` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`metricid`),
  UNIQUE KEY `unique-metric` (`userid`,`host`,`name`,`sampleid`)
) ENGINE=InnoDB AUTO_INCREMENT=1000000000000 DEFAULT CHARSET=utf8

Каждый сервер (идентификаторы 1,2,3) выполняет этот запрос каждую секунду:

insert into metric set metricid = $serverId$now, host = $now, name = $serverId

(e.g. insert into metric set metricid = 31396887217, host = 1396887217, name = 3)

И довольно быстро я сталкиваюсь с «ОШИБКОЙ 1213 (40001) в строке 1: обнаружена взаимоблокировка при попытке получить блокировку; попробуйте перезапустить транзакцию» - учитывая, что я предоставляю идентификаторы, которые не перекрываются, поскольку каждый сервер создает идентификатор с другим префиксом , почему взаимоблокировки вообще случаются?


person Fluffy    schedule 07.04.2014    source источник


Ответы (1)


Конфликт возникает из-за того, что INSERT фактически блокирует «пробел», в который он вставляется. В случае вставки в конец таблицы он фактически блокирует промежуток, который находится после всех существующих строк (и теоретически простирается до бесконечности.

Ситуация усложняется тем фактом, что у вас есть второе ограничение UNIQUE KEY, поэтому, когда вы запускаете два одновременных сеанса, InnoDB необходимо создать две блокировки промежутка, одну для PRIMARY KEY и одну для UNIQUE KEY. Следовательно, возможно состояние гонки, когда два сеанса могут получить свои блокировки таким образом, что в конечном итоге они будут ждать друг друга.

Мне интересно, почему у вас есть первичный ключ AUTO_INCREMENT, но вы переопределяете функцию автоинкремента. Использование автоинкремента может помочь, поскольку автоинкремент разрешается с помощью очень короткой блокировки таблицы, и, следовательно, вы можете избежать взаимоблокировки, поскольку у вас будет только одна блокировка пробела. Однако я не проверял эту идею.

Смотрите также:

person Bill Karwin    schedule 07.04.2014